foundation-ai-agent 1.0.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 +338 -0
- package/dist/compat/butler-cloud.d.ts +33 -0
- package/dist/compat/butler-cloud.d.ts.map +1 -0
- package/dist/compat/butler-cloud.js +69 -0
- package/dist/compat/butler-cloud.js.map +1 -0
- package/dist/compat/butler-edge.d.ts +34 -0
- package/dist/compat/butler-edge.d.ts.map +1 -0
- package/dist/compat/butler-edge.js +62 -0
- package/dist/compat/butler-edge.js.map +1 -0
- package/dist/compat/butler-pair.d.ts +27 -0
- package/dist/compat/butler-pair.d.ts.map +1 -0
- package/dist/compat/butler-pair.js +23 -0
- package/dist/compat/butler-pair.js.map +1 -0
- package/dist/compat/entry.d.ts +26 -0
- package/dist/compat/entry.d.ts.map +1 -0
- package/dist/compat/entry.js +35 -0
- package/dist/compat/entry.js.map +1 -0
- package/dist/compat/index.d.ts +12 -0
- package/dist/compat/index.d.ts.map +1 -0
- package/dist/compat/index.js +12 -0
- package/dist/compat/index.js.map +1 -0
- package/dist/compat/queue.d.ts +31 -0
- package/dist/compat/queue.d.ts.map +1 -0
- package/dist/compat/queue.js +54 -0
- package/dist/compat/queue.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/ledger.d.ts +28 -0
- package/dist/ledger.d.ts.map +1 -0
- package/dist/ledger.js +62 -0
- package/dist/ledger.js.map +1 -0
- package/dist/observability/index.d.ts +4 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +2 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/observer.d.ts +37 -0
- package/dist/observability/observer.d.ts.map +1 -0
- package/dist/observability/observer.js +53 -0
- package/dist/observability/observer.js.map +1 -0
- package/dist/observability/types.d.ts +92 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +9 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/s01-realtime/index.d.ts +3 -0
- package/dist/s01-realtime/index.d.ts.map +1 -0
- package/dist/s01-realtime/index.js +2 -0
- package/dist/s01-realtime/index.js.map +1 -0
- package/dist/s01-realtime/signaling.d.ts +78 -0
- package/dist/s01-realtime/signaling.d.ts.map +1 -0
- package/dist/s01-realtime/signaling.js +20 -0
- package/dist/s01-realtime/signaling.js.map +1 -0
- package/dist/s01-realtime/types.d.ts +40 -0
- package/dist/s01-realtime/types.d.ts.map +1 -0
- package/dist/s01-realtime/types.js +8 -0
- package/dist/s01-realtime/types.js.map +1 -0
- package/dist/s02-crdt/index.d.ts +3 -0
- package/dist/s02-crdt/index.d.ts.map +1 -0
- package/dist/s02-crdt/index.js +2 -0
- package/dist/s02-crdt/index.js.map +1 -0
- package/dist/s02-crdt/types.d.ts +45 -0
- package/dist/s02-crdt/types.d.ts.map +1 -0
- package/dist/s02-crdt/types.js +10 -0
- package/dist/s02-crdt/types.js.map +1 -0
- package/dist/s02-crdt/yjs.d.ts +9 -0
- package/dist/s02-crdt/yjs.d.ts.map +1 -0
- package/dist/s02-crdt/yjs.js +67 -0
- package/dist/s02-crdt/yjs.js.map +1 -0
- package/dist/s03-streaming/index.d.ts +3 -0
- package/dist/s03-streaming/index.d.ts.map +1 -0
- package/dist/s03-streaming/index.js +2 -0
- package/dist/s03-streaming/index.js.map +1 -0
- package/dist/s03-streaming/playlist.d.ts +8 -0
- package/dist/s03-streaming/playlist.d.ts.map +1 -0
- package/dist/s03-streaming/playlist.js +49 -0
- package/dist/s03-streaming/playlist.js.map +1 -0
- package/dist/s03-streaming/types.d.ts +69 -0
- package/dist/s03-streaming/types.d.ts.map +1 -0
- package/dist/s03-streaming/types.js +8 -0
- package/dist/s03-streaming/types.js.map +1 -0
- package/dist/s04-messaging/index.d.ts +3 -0
- package/dist/s04-messaging/index.d.ts.map +1 -0
- package/dist/s04-messaging/index.js +2 -0
- package/dist/s04-messaging/index.js.map +1 -0
- package/dist/s04-messaging/serializer.d.ts +11 -0
- package/dist/s04-messaging/serializer.d.ts.map +1 -0
- package/dist/s04-messaging/serializer.js +45 -0
- package/dist/s04-messaging/serializer.js.map +1 -0
- package/dist/s04-messaging/types.d.ts +54 -0
- package/dist/s04-messaging/types.d.ts.map +1 -0
- package/dist/s04-messaging/types.js +8 -0
- package/dist/s04-messaging/types.js.map +1 -0
- package/dist/s05-rendering/index.d.ts +3 -0
- package/dist/s05-rendering/index.d.ts.map +1 -0
- package/dist/s05-rendering/index.js +3 -0
- package/dist/s05-rendering/index.js.map +1 -0
- package/dist/s05-rendering/state-machine.d.ts +20 -0
- package/dist/s05-rendering/state-machine.d.ts.map +1 -0
- package/dist/s05-rendering/state-machine.js +47 -0
- package/dist/s05-rendering/state-machine.js.map +1 -0
- package/dist/s05-rendering/types.d.ts +13 -0
- package/dist/s05-rendering/types.d.ts.map +1 -0
- package/dist/s05-rendering/types.js +16 -0
- package/dist/s05-rendering/types.js.map +1 -0
- package/dist/s06-payments/billing.d.ts +9 -0
- package/dist/s06-payments/billing.d.ts.map +1 -0
- package/dist/s06-payments/billing.js +79 -0
- package/dist/s06-payments/billing.js.map +1 -0
- package/dist/s06-payments/index.d.ts +4 -0
- package/dist/s06-payments/index.d.ts.map +1 -0
- package/dist/s06-payments/index.js +3 -0
- package/dist/s06-payments/index.js.map +1 -0
- package/dist/s06-payments/stripe.d.ts +52 -0
- package/dist/s06-payments/stripe.d.ts.map +1 -0
- package/dist/s06-payments/stripe.js +103 -0
- package/dist/s06-payments/stripe.js.map +1 -0
- package/dist/s06-payments/types.d.ts +80 -0
- package/dist/s06-payments/types.d.ts.map +1 -0
- package/dist/s06-payments/types.js +13 -0
- package/dist/s06-payments/types.js.map +1 -0
- package/dist/s07-identity/index.d.ts +2 -0
- package/dist/s07-identity/index.d.ts.map +1 -0
- package/dist/s07-identity/index.js +2 -0
- package/dist/s07-identity/index.js.map +1 -0
- package/dist/s07-identity/session.d.ts +53 -0
- package/dist/s07-identity/session.d.ts.map +1 -0
- package/dist/s07-identity/session.js +114 -0
- package/dist/s07-identity/session.js.map +1 -0
- package/dist/s08-containers/docker.d.ts +39 -0
- package/dist/s08-containers/docker.d.ts.map +1 -0
- package/dist/s08-containers/docker.js +72 -0
- package/dist/s08-containers/docker.js.map +1 -0
- package/dist/s08-containers/index.d.ts +4 -0
- package/dist/s08-containers/index.d.ts.map +1 -0
- package/dist/s08-containers/index.js +3 -0
- package/dist/s08-containers/index.js.map +1 -0
- package/dist/s08-containers/sandbox.d.ts +10 -0
- package/dist/s08-containers/sandbox.d.ts.map +1 -0
- package/dist/s08-containers/sandbox.js +68 -0
- package/dist/s08-containers/sandbox.js.map +1 -0
- package/dist/s08-containers/types.d.ts +66 -0
- package/dist/s08-containers/types.d.ts.map +1 -0
- package/dist/s08-containers/types.js +8 -0
- package/dist/s08-containers/types.js.map +1 -0
- package/dist/s09-persistence/cold.d.ts +43 -0
- package/dist/s09-persistence/cold.d.ts.map +1 -0
- package/dist/s09-persistence/cold.js +135 -0
- package/dist/s09-persistence/cold.js.map +1 -0
- package/dist/s09-persistence/hot.d.ts +32 -0
- package/dist/s09-persistence/hot.d.ts.map +1 -0
- package/dist/s09-persistence/hot.js +63 -0
- package/dist/s09-persistence/hot.js.map +1 -0
- package/dist/s09-persistence/index.d.ts +6 -0
- package/dist/s09-persistence/index.d.ts.map +1 -0
- package/dist/s09-persistence/index.js +6 -0
- package/dist/s09-persistence/index.js.map +1 -0
- package/dist/s09-persistence/pg-warm.d.ts +30 -0
- package/dist/s09-persistence/pg-warm.d.ts.map +1 -0
- package/dist/s09-persistence/pg-warm.js +139 -0
- package/dist/s09-persistence/pg-warm.js.map +1 -0
- package/dist/s09-persistence/s3-cold.d.ts +39 -0
- package/dist/s09-persistence/s3-cold.d.ts.map +1 -0
- package/dist/s09-persistence/s3-cold.js +102 -0
- package/dist/s09-persistence/s3-cold.js.map +1 -0
- package/dist/s09-persistence/warm.d.ts +33 -0
- package/dist/s09-persistence/warm.d.ts.map +1 -0
- package/dist/s09-persistence/warm.js +169 -0
- package/dist/s09-persistence/warm.js.map +1 -0
- package/dist/s10-inference/action.d.ts +39 -0
- package/dist/s10-inference/action.d.ts.map +1 -0
- package/dist/s10-inference/action.js +73 -0
- package/dist/s10-inference/action.js.map +1 -0
- package/dist/s10-inference/agents/index.d.ts +3 -0
- package/dist/s10-inference/agents/index.d.ts.map +1 -0
- package/dist/s10-inference/agents/index.js +3 -0
- package/dist/s10-inference/agents/index.js.map +1 -0
- package/dist/s10-inference/agents/mirror.d.ts +73 -0
- package/dist/s10-inference/agents/mirror.d.ts.map +1 -0
- package/dist/s10-inference/agents/mirror.js +106 -0
- package/dist/s10-inference/agents/mirror.js.map +1 -0
- package/dist/s10-inference/agents/registry.d.ts +64 -0
- package/dist/s10-inference/agents/registry.d.ts.map +1 -0
- package/dist/s10-inference/agents/registry.js +92 -0
- package/dist/s10-inference/agents/registry.js.map +1 -0
- package/dist/s10-inference/context.d.ts +39 -0
- package/dist/s10-inference/context.d.ts.map +1 -0
- package/dist/s10-inference/context.js +36 -0
- package/dist/s10-inference/context.js.map +1 -0
- package/dist/s10-inference/index.d.ts +7 -0
- package/dist/s10-inference/index.d.ts.map +1 -0
- package/dist/s10-inference/index.js +6 -0
- package/dist/s10-inference/index.js.map +1 -0
- package/dist/s10-inference/loop.d.ts +42 -0
- package/dist/s10-inference/loop.d.ts.map +1 -0
- package/dist/s10-inference/loop.js +104 -0
- package/dist/s10-inference/loop.js.map +1 -0
- package/dist/s10-inference/provider.d.ts +43 -0
- package/dist/s10-inference/provider.d.ts.map +1 -0
- package/dist/s10-inference/provider.js +9 -0
- package/dist/s10-inference/provider.js.map +1 -0
- package/dist/s10-inference/providers/anthropic.d.ts +13 -0
- package/dist/s10-inference/providers/anthropic.d.ts.map +1 -0
- package/dist/s10-inference/providers/anthropic.js +168 -0
- package/dist/s10-inference/providers/anthropic.js.map +1 -0
- package/dist/s10-inference/providers/ollama.d.ts +9 -0
- package/dist/s10-inference/providers/ollama.d.ts.map +1 -0
- package/dist/s10-inference/providers/ollama.js +102 -0
- package/dist/s10-inference/providers/ollama.js.map +1 -0
- package/dist/s10-inference/providers/openai.d.ts +14 -0
- package/dist/s10-inference/providers/openai.d.ts.map +1 -0
- package/dist/s10-inference/providers/openai.js +172 -0
- package/dist/s10-inference/providers/openai.js.map +1 -0
- package/dist/s11-transport/index.d.ts +4 -0
- package/dist/s11-transport/index.d.ts.map +1 -0
- package/dist/s11-transport/index.js +4 -0
- package/dist/s11-transport/index.js.map +1 -0
- package/dist/s11-transport/room.d.ts +28 -0
- package/dist/s11-transport/room.d.ts.map +1 -0
- package/dist/s11-transport/room.js +69 -0
- package/dist/s11-transport/room.js.map +1 -0
- package/dist/s11-transport/transport.d.ts +20 -0
- package/dist/s11-transport/transport.d.ts.map +1 -0
- package/dist/s11-transport/transport.js +39 -0
- package/dist/s11-transport/transport.js.map +1 -0
- package/dist/s11-transport/ws.d.ts +15 -0
- package/dist/s11-transport/ws.d.ts.map +1 -0
- package/dist/s11-transport/ws.js +71 -0
- package/dist/s11-transport/ws.js.map +1 -0
- package/dist/s12-versioncontrol/index.d.ts +4 -0
- package/dist/s12-versioncontrol/index.d.ts.map +1 -0
- package/dist/s12-versioncontrol/index.js +3 -0
- package/dist/s12-versioncontrol/index.js.map +1 -0
- package/dist/s12-versioncontrol/ledger-dag.d.ts +25 -0
- package/dist/s12-versioncontrol/ledger-dag.d.ts.map +1 -0
- package/dist/s12-versioncontrol/ledger-dag.js +84 -0
- package/dist/s12-versioncontrol/ledger-dag.js.map +1 -0
- package/dist/s12-versioncontrol/merkle.d.ts +16 -0
- package/dist/s12-versioncontrol/merkle.d.ts.map +1 -0
- package/dist/s12-versioncontrol/merkle.js +81 -0
- package/dist/s12-versioncontrol/merkle.js.map +1 -0
- package/dist/s12-versioncontrol/types.d.ts +50 -0
- package/dist/s12-versioncontrol/types.d.ts.map +1 -0
- package/dist/s12-versioncontrol/types.js +8 -0
- package/dist/s12-versioncontrol/types.js.map +1 -0
- package/dist/touches/audio-tap.d.ts +32 -0
- package/dist/touches/audio-tap.d.ts.map +1 -0
- package/dist/touches/audio-tap.js +54 -0
- package/dist/touches/audio-tap.js.map +1 -0
- package/dist/touches/avatar-state.d.ts +22 -0
- package/dist/touches/avatar-state.d.ts.map +1 -0
- package/dist/touches/avatar-state.js +35 -0
- package/dist/touches/avatar-state.js.map +1 -0
- package/dist/touches/container-room.d.ts +17 -0
- package/dist/touches/container-room.d.ts.map +1 -0
- package/dist/touches/container-room.js +34 -0
- package/dist/touches/container-room.js.map +1 -0
- package/dist/touches/cost-billing.d.ts +20 -0
- package/dist/touches/cost-billing.d.ts.map +1 -0
- package/dist/touches/cost-billing.js +26 -0
- package/dist/touches/cost-billing.js.map +1 -0
- package/dist/touches/cost-track.d.ts +19 -0
- package/dist/touches/cost-track.d.ts.map +1 -0
- package/dist/touches/cost-track.js +20 -0
- package/dist/touches/cost-track.js.map +1 -0
- package/dist/touches/crdt-sync.d.ts +14 -0
- package/dist/touches/crdt-sync.d.ts.map +1 -0
- package/dist/touches/crdt-sync.js +49 -0
- package/dist/touches/crdt-sync.js.map +1 -0
- package/dist/touches/identity-gate.d.ts +22 -0
- package/dist/touches/identity-gate.d.ts.map +1 -0
- package/dist/touches/identity-gate.js +24 -0
- package/dist/touches/identity-gate.js.map +1 -0
- package/dist/touches/index.d.ts +14 -0
- package/dist/touches/index.d.ts.map +1 -0
- package/dist/touches/index.js +14 -0
- package/dist/touches/index.js.map +1 -0
- package/dist/touches/memory-persist.d.ts +29 -0
- package/dist/touches/memory-persist.d.ts.map +1 -0
- package/dist/touches/memory-persist.js +49 -0
- package/dist/touches/memory-persist.js.map +1 -0
- package/dist/touches/messenger-bridge.d.ts +19 -0
- package/dist/touches/messenger-bridge.d.ts.map +1 -0
- package/dist/touches/messenger-bridge.js +49 -0
- package/dist/touches/messenger-bridge.js.map +1 -0
- package/dist/touches/sentiment-tap.d.ts +43 -0
- package/dist/touches/sentiment-tap.d.ts.map +1 -0
- package/dist/touches/sentiment-tap.js +81 -0
- package/dist/touches/sentiment-tap.js.map +1 -0
- package/dist/touches/stichwort.d.ts +46 -0
- package/dist/touches/stichwort.d.ts.map +1 -0
- package/dist/touches/stichwort.js +64 -0
- package/dist/touches/stichwort.js.map +1 -0
- package/dist/touches/transport-signal.d.ts +26 -0
- package/dist/touches/transport-signal.d.ts.map +1 -0
- package/dist/touches/transport-signal.js +49 -0
- package/dist/touches/transport-signal.js.map +1 -0
- package/dist/touches/version-persist.d.ts +18 -0
- package/dist/touches/version-persist.d.ts.map +1 -0
- package/dist/touches/version-persist.js +38 -0
- package/dist/touches/version-persist.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +117 -0
package/README.md
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# foundation
|
|
2
|
+
|
|
3
|
+
12 layers. Native. Zero wrappers.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
S01 Realtime S05 Rendering S09 Persistence
|
|
7
|
+
S02 CRDTs S06 Payments S10 Inference
|
|
8
|
+
S03 Streaming S07 Identity S11 Transport
|
|
9
|
+
S04 Messaging S08 Containers S12 Version Control
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Foundation is not a framework. It is a protocol for AI agent systems.
|
|
13
|
+
|
|
14
|
+
TCP/IP defined what a network is. Foundation defines what an AI agent system is. Every provider, every transport, every memory tier, every consent model plugs in through the same interfaces. No vendor lock-in. No SDK dependencies. No wrappers.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## The Architecture
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
src/
|
|
22
|
+
├── sXX-name/ Layers. Each stands alone. No cross-imports.
|
|
23
|
+
├── touches/ The only bridges between layers. Explicit coupling.
|
|
24
|
+
└── compat/ External system bridges. NOT part of the foundation.
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**One rule governs the entire system:** Layers never import from sibling layers. All cross-layer integration goes through `touches/` -- named, tested, explicit connection points. If two layers need to talk, there is a file in `touches/` that says exactly how.
|
|
28
|
+
|
|
29
|
+
### The 12 Layers
|
|
30
|
+
|
|
31
|
+
| Layer | What it does | Key primitive |
|
|
32
|
+
|-------|-------------|---------------|
|
|
33
|
+
| **S01 Realtime** | WebRTC signaling, media types | `SignalingMessage` (11 types) |
|
|
34
|
+
| **S02 CRDTs** | Distributed state synchronization | `SharedDoc` (interface-first, yjs impl) |
|
|
35
|
+
| **S03 Streaming** | HLS/DASH segmentation, codecs | `Segmenter`, `PlaylistManager` |
|
|
36
|
+
| **S04 Messaging** | Chat, briefings, notifications | `Channel` (platform-agnostic) |
|
|
37
|
+
| **S05 Rendering** | State machines, avatar gestures | `StateMachine<S, E>` (generic) |
|
|
38
|
+
| **S06 Payments** | Billing, subscriptions, usage | `BillingService` (interface-first) |
|
|
39
|
+
| **S07 Identity** | Consent as authorization | `observe / assist / act` |
|
|
40
|
+
| **S08 Containers** | Process isolation, GPU scheduling | `Sandbox`, `GpuScheduler` |
|
|
41
|
+
| **S09 Persistence** | Three-tier cognitive memory | `HOT → WARM → COLD` |
|
|
42
|
+
| **S10 Inference** | Provider-agnostic agent loop | `Provider.stream()` → 4 Chunk types |
|
|
43
|
+
| **S11 Transport** | Network abstraction | `send()` + `receive()` |
|
|
44
|
+
| **S12 Version Control** | Merkle trees for decision audit | `buildTree()`, `verifyProof()` |
|
|
45
|
+
|
|
46
|
+
### The Touch Points
|
|
47
|
+
|
|
48
|
+
Every connection between layers is a file. Every file is small. The average touch point is 60 lines.
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
audio-tap.ts S01 ↔ S10 Audio → Transcript → Tokens
|
|
52
|
+
stichwort.ts S01 ↔ S10 Keyword detection (pure pipeline)
|
|
53
|
+
transport-signal.ts S01 ↔ S11 Signaling ↔ Transport events
|
|
54
|
+
crdt-sync.ts S02 ↔ S11 CRDT updates ↔ Transport events
|
|
55
|
+
messenger-bridge.ts S04 ↔ S10 Briefing generation via Loop
|
|
56
|
+
avatar-state.ts S05 ↔ S10 Inference events → Avatar transitions
|
|
57
|
+
cost-billing.ts S06 ↔ Ledger Consent tiers → Pricing tiers
|
|
58
|
+
identity-gate.ts S07 ↔ S10 observe=deny, assist=ask, act=allow
|
|
59
|
+
container-room.ts S08 ↔ S11 Room → Container isolation
|
|
60
|
+
memory-persist.ts S09 ↔ S10 HOT → compact → WARM → flush → COLD
|
|
61
|
+
cost-track.ts S10 ↔ Ledger Usage → Cost tracking
|
|
62
|
+
version-persist.ts S12 ↔ S09 Merkle DAG → COLD storage
|
|
63
|
+
sentiment-tap.ts S01 ↔ S10 Audio → Emotion → Dynamics
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## The Numbers
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
74 source files 43 test suites 376 tests
|
|
72
|
+
12/12 layers 13 touch points 3 runtime deps
|
|
73
|
+
3 providers 0 SDK wrappers 0 AI framework imports
|
|
74
|
+
5 production backends (Postgres, S3, Stripe, Docker, Observability)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Three runtime dependencies. Each is infrastructure, not abstraction:
|
|
78
|
+
|
|
79
|
+
| Dependency | Why |
|
|
80
|
+
|------------|-----|
|
|
81
|
+
| `better-sqlite3` | WARM memory (S09) |
|
|
82
|
+
| `ws` | WebSocket transport (S11) |
|
|
83
|
+
| `yjs` | CRDT implementation (S02) |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Quick Start
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install
|
|
91
|
+
npm test # 347 tests
|
|
92
|
+
npm run check # tsc --noEmit
|
|
93
|
+
npm run build # emit dist/
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Use a provider
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { createOllamaProvider, loop, createContext } from 'foundation'
|
|
100
|
+
|
|
101
|
+
const provider = createOllamaProvider() // localhost:11434
|
|
102
|
+
const ctx = createContext({ model: 'qwen2.5:3b', root: '.' })
|
|
103
|
+
|
|
104
|
+
const gen = loop({
|
|
105
|
+
messages: [{ id: '1', role: 'user', content: 'Hello', ts: Date.now() }],
|
|
106
|
+
system: 'Be helpful.',
|
|
107
|
+
actions: [],
|
|
108
|
+
provider,
|
|
109
|
+
ctx,
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
for await (const msg of gen) {
|
|
113
|
+
console.log(msg.role, typeof msg.content === 'string' ? msg.content : '[blocks]')
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Add actions
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import { ok, type Action } from 'foundation'
|
|
121
|
+
|
|
122
|
+
const search: Action = {
|
|
123
|
+
name: 'search',
|
|
124
|
+
schema: { name: 'search', description: 'Search', parameters: { type: 'object', properties: { q: { type: 'string' } } } },
|
|
125
|
+
concurrent: true,
|
|
126
|
+
validate: (input) => ok(input),
|
|
127
|
+
gate: () => 'allow',
|
|
128
|
+
execute: async (input) => ok(`Results for ${JSON.stringify(input)}`),
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Pass to loop({ ... actions: [search] })
|
|
132
|
+
// The loop calls validate → gate → execute, batches concurrent actions
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Three-tier memory
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import { createHotMemory, createWarmMemory, createFsColdMemory, createMemoryStack } from 'foundation'
|
|
139
|
+
|
|
140
|
+
const hot = createHotMemory({ budget: 50_000 })
|
|
141
|
+
const warm = createWarmMemory('./data/warm.db')
|
|
142
|
+
const cold = createFsColdMemory('./data/cold')
|
|
143
|
+
const memory = createMemoryStack(hot, warm, cold)
|
|
144
|
+
|
|
145
|
+
// During session: memory.maintain(50_000) compacts when over budget
|
|
146
|
+
// End of session: memory.flushToCold('session-id') archives everything
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Consent as a layer
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { createIdentity, consentToGate } from 'foundation'
|
|
153
|
+
|
|
154
|
+
const identity = createIdentity()
|
|
155
|
+
const session = identity.initDefaults('user-1')
|
|
156
|
+
|
|
157
|
+
// Check: can this agent suggest queue items?
|
|
158
|
+
const gate = consentToGate(identity, session, { feature: 'queue_suggest', required: 'assist' })
|
|
159
|
+
// gate === 'ask' (assist level = host must approve)
|
|
160
|
+
|
|
161
|
+
// Upgrade to autonomous
|
|
162
|
+
identity.setScope(session, 'queue_suggest', 'act')
|
|
163
|
+
const gate2 = consentToGate(identity, session, { feature: 'queue_suggest', required: 'assist' })
|
|
164
|
+
// gate2 === 'allow' (act level = agent can act autonomously)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Multi-agent
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { createAgentRegistry, createOllamaProvider, createAnthropicProvider } from 'foundation'
|
|
171
|
+
|
|
172
|
+
const registry = createAgentRegistry()
|
|
173
|
+
|
|
174
|
+
registry.register({
|
|
175
|
+
name: 'sebastian-edge',
|
|
176
|
+
role: 'classifier',
|
|
177
|
+
provider: createOllamaProvider(),
|
|
178
|
+
model: 'qwen2.5:3b',
|
|
179
|
+
mode: 'act',
|
|
180
|
+
budgetCents: 100,
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
registry.register({
|
|
184
|
+
name: 'sebastian-cloud',
|
|
185
|
+
role: 'researcher',
|
|
186
|
+
provider: createAnthropicProvider({ apiKey: '...' }),
|
|
187
|
+
model: 'claude-sonnet-4-6',
|
|
188
|
+
mode: 'assist',
|
|
189
|
+
budgetCents: 5000,
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
registry.perAgent() // cost breakdown per agent
|
|
193
|
+
registry.perOrg() // aggregated per organization
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Design Decisions
|
|
199
|
+
|
|
200
|
+
### Errors are values
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
No exceptions for control flow. Every function that can fail returns `Result`. Pattern-match on `ok`, not try-catch.
|
|
207
|
+
|
|
208
|
+
### 4 chunk types standardize all providers
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
type Chunk =
|
|
212
|
+
| { type: 'text'; text: string }
|
|
213
|
+
| { type: 'action_call'; id: string; name: string; input: unknown }
|
|
214
|
+
| { type: 'usage'; tokens: TokenUsage }
|
|
215
|
+
| { type: 'done'; reason: 'complete' | 'action_calls' }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Ollama, Anthropic, OpenAI -- all produce the same 4 chunk types. The loop doesn't know which provider it's talking to.
|
|
219
|
+
|
|
220
|
+
### Interface first, implementation second
|
|
221
|
+
|
|
222
|
+
Every layer defines its contract as a TypeScript type. The implementation is one of many possible:
|
|
223
|
+
|
|
224
|
+
- `Provider` interface → Ollama, Anthropic, OpenAI implementations
|
|
225
|
+
- `SharedDoc` interface → yjs implementation (Automerge, diamond-types possible)
|
|
226
|
+
- `Transport` interface → WebSocket, local, IPC implementations
|
|
227
|
+
- `ColdMemory` interface → Filesystem + S3/R2 implementations
|
|
228
|
+
- `BillingService` interface → In-memory + Stripe implementations
|
|
229
|
+
- `Sandbox` interface → In-memory + Docker implementations
|
|
230
|
+
|
|
231
|
+
### Open unions
|
|
232
|
+
|
|
233
|
+
Every union type is extensible:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
type EntryCategory = 'decision' | 'fact' | 'action_item' | ... | (string & {})
|
|
237
|
+
type ArtifactType = 'transcript' | 'document' | 'media' | ... | (string & {})
|
|
238
|
+
type Feature = 'listening' | 'mirror_mode' | ... | (string & {})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
No layer is closed. No external system is locked out.
|
|
242
|
+
|
|
243
|
+
### Consent is not a feature -- it is infrastructure
|
|
244
|
+
|
|
245
|
+
Three levels. Three meanings. One mapping:
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
observe → deny (can only watch)
|
|
249
|
+
assist → ask (can suggest, host approves)
|
|
250
|
+
act → allow (autonomous action)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
This maps 1:1 to pricing tiers (free/professional/enterprise), gate decisions (deny/ask/allow), and autonomy levels. It is the single most load-bearing abstraction in the system.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## What Emerges
|
|
258
|
+
|
|
259
|
+
Properties that no single layer has alone:
|
|
260
|
+
|
|
261
|
+
| Combination | Emergence |
|
|
262
|
+
|-------------|-----------|
|
|
263
|
+
| S07 + S10 | Ethical autonomy -- consent gates action execution |
|
|
264
|
+
| S09 HOT+WARM+COLD | Cognitive memory -- compaction = memory formation |
|
|
265
|
+
| S06 + S07 | Monetized autonomy -- consent levels = pricing tiers |
|
|
266
|
+
| S08 + S10 | Isolated execution -- each agent in its own sandbox |
|
|
267
|
+
| S12 + S09 | Auditable history -- Merkle proofs for every decision |
|
|
268
|
+
| All 12 layers | Mirror Mode -- autonomous agent with ethical boundary, cost limit, audit trail, visual transparency |
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## The Proof
|
|
273
|
+
|
|
274
|
+
The architecture was validated empirically, not by argument:
|
|
275
|
+
|
|
276
|
+
**376 tests** prove that layers compose. Integration tests cross layer boundaries. E2E tests hit real Ollama and real WebSocket servers.
|
|
277
|
+
|
|
278
|
+
**4 Butler adapters under 100 lines each** prove that the interfaces match reality. The prediction was made before M1. The proof came at M13. Thin adapters = correct abstractions.
|
|
279
|
+
|
|
280
|
+
**0room0 imports Foundation** for Memory, Consent, Provider, StateMachine. The first external consumer confirmed: Foundation types flow cleanly into a real product with 346 tests.
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Project Structure
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
foundation/
|
|
288
|
+
├── src/
|
|
289
|
+
│ ├── index.ts Public API
|
|
290
|
+
│ ├── types.ts Result, Message, Entry, Event
|
|
291
|
+
│ ├── ledger.ts Cost tracking
|
|
292
|
+
│ │
|
|
293
|
+
│ ├── s01-realtime/ WebRTC signaling + media types
|
|
294
|
+
│ ├── s02-crdt/ SharedDoc interface + yjs
|
|
295
|
+
│ ├── s03-streaming/ HLS segmentation + playlists
|
|
296
|
+
│ ├── s04-messaging/ Chat, briefings, channels
|
|
297
|
+
│ ├── s05-rendering/ StateMachine + avatar gestures
|
|
298
|
+
│ ├── s06-payments/ Billing + subscriptions
|
|
299
|
+
│ ├── s07-identity/ Consent (observe/assist/act)
|
|
300
|
+
│ ├── s08-containers/ Sandbox + GPU scheduler
|
|
301
|
+
│ ├── s09-persistence/ HOT (memory) + WARM (SQLite) + COLD (fs)
|
|
302
|
+
│ ├── s10-inference/ Provider → Action → Loop
|
|
303
|
+
│ │ ├── providers/ Ollama, Anthropic, OpenAI (raw fetch)
|
|
304
|
+
│ │ └── agents/ Multi-agent registry, mirror mode
|
|
305
|
+
│ ├── s11-transport/ Transport + WebSocket + Room
|
|
306
|
+
│ ├── s12-versioncontrol/ Merkle trees + DAG
|
|
307
|
+
│ │
|
|
308
|
+
│ ├── touches/ 13 cross-layer bridges
|
|
309
|
+
│ └── compat/ External system bridges
|
|
310
|
+
│
|
|
311
|
+
├── tests/
|
|
312
|
+
│ ├── s01/ ... s12/ Unit tests per layer
|
|
313
|
+
│ ├── touches/ Touch point tests
|
|
314
|
+
│ ├── integration/ Cross-layer composition tests
|
|
315
|
+
│ └── e2e/ Live Ollama + WebSocket tests
|
|
316
|
+
│
|
|
317
|
+
├── ROADMAP.md 23-milestone plan (completed)
|
|
318
|
+
└── M14-PLAN.md 0room0 integration playbook
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## TypeScript
|
|
324
|
+
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"strict": true,
|
|
328
|
+
"noUncheckedIndexedAccess": true,
|
|
329
|
+
"target": "ES2022",
|
|
330
|
+
"module": "NodeNext"
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
No `any`. No unguarded index access. `Result<T,E>` everywhere. `Context<Ext>` is generic for type-safe domain extensions.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
*Built in one session. 23 milestones. Two parallel agents -- one builds, one observes. Every correction was applied. Every blind spot was closed. The foundation holds.*
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT — Cloud Butler Adapter
|
|
3
|
+
*
|
|
4
|
+
* Wraps Foundation Provider + Loop + Actions als CloudButler Interface.
|
|
5
|
+
* Der Cloud-Butler exekutiert: research, draft, create, validate, summarize.
|
|
6
|
+
* Bekommt Query vom Edge-Butler, liefert Material für die Queue.
|
|
7
|
+
*
|
|
8
|
+
* Messpunkt: Unter 100 Zeilen = Interfaces stimmen.
|
|
9
|
+
*/
|
|
10
|
+
import type { Provider } from '../s10-inference/provider.js';
|
|
11
|
+
import type { Context } from '../s10-inference/context.js';
|
|
12
|
+
import type { Action } from '../s10-inference/action.js';
|
|
13
|
+
import { type Result } from '../types.js';
|
|
14
|
+
export type CloudTaskType = 'research' | 'draft' | 'create' | 'validate' | 'summarize' | (string & {});
|
|
15
|
+
export type CloudTask = {
|
|
16
|
+
type: CloudTaskType;
|
|
17
|
+
query: string;
|
|
18
|
+
maxTokens?: number;
|
|
19
|
+
priority?: 'low' | 'normal' | 'high';
|
|
20
|
+
};
|
|
21
|
+
export type CloudOutput = {
|
|
22
|
+
title: string;
|
|
23
|
+
summary: string;
|
|
24
|
+
content: string;
|
|
25
|
+
confidence: number;
|
|
26
|
+
sources: string[];
|
|
27
|
+
gaps: string[];
|
|
28
|
+
};
|
|
29
|
+
export type CloudButler = {
|
|
30
|
+
execute(task: CloudTask, ledgerContext: string): Promise<Result<CloudOutput, string>>;
|
|
31
|
+
};
|
|
32
|
+
export declare function createCloudButler(provider: Provider, actions: readonly Action[], ctx: Context): CloudButler;
|
|
33
|
+
//# sourceMappingURL=butler-cloud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butler-cloud.d.ts","sourceRoot":"","sources":["../../src/compat/butler-cloud.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AAExD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAElD,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,WAAW,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEtG,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,aAAa,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,IAAI,EAAE,MAAM,EAAE,CAAA;CACf,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAA;CACtF,CAAA;AAQD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,GAAG,EAAE,OAAO,GACX,WAAW,CAkDb"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT — Cloud Butler Adapter
|
|
3
|
+
*
|
|
4
|
+
* Wraps Foundation Provider + Loop + Actions als CloudButler Interface.
|
|
5
|
+
* Der Cloud-Butler exekutiert: research, draft, create, validate, summarize.
|
|
6
|
+
* Bekommt Query vom Edge-Butler, liefert Material für die Queue.
|
|
7
|
+
*
|
|
8
|
+
* Messpunkt: Unter 100 Zeilen = Interfaces stimmen.
|
|
9
|
+
*/
|
|
10
|
+
import { loop } from '../s10-inference/loop.js';
|
|
11
|
+
import { ok, err } from '../types.js';
|
|
12
|
+
const CLOUD_SYSTEM_PROMPT = `Du bist Sebastian-Außen, ein Research-Butler.
|
|
13
|
+
Du erfindest NICHTS. Keine Quellen = keine Antwort. Wahrheit vor Höflichkeit.
|
|
14
|
+
Antworte als JSON: {"title":"...","summary":"...","content":"...","confidence":0.0-1.0,"sources":["..."],"gaps":["..."]}
|
|
15
|
+
confidence: high(>0.7), medium(0.4-0.7), low(<0.4). Sei ehrlich.
|
|
16
|
+
gaps: Was fehlt? Was konntest du nicht prüfen?`;
|
|
17
|
+
export function createCloudButler(provider, actions, ctx) {
|
|
18
|
+
return {
|
|
19
|
+
async execute(task, ledgerContext) {
|
|
20
|
+
const userMsg = [
|
|
21
|
+
`Aufgabe: ${task.type}`,
|
|
22
|
+
`Frage: ${task.query}`,
|
|
23
|
+
ledgerContext ? `Kontext:\n${ledgerContext}` : '',
|
|
24
|
+
].filter(Boolean).join('\n');
|
|
25
|
+
const gen = loop({
|
|
26
|
+
messages: [{ id: 'cloud-in', role: 'user', content: userMsg, ts: Date.now() }],
|
|
27
|
+
system: CLOUD_SYSTEM_PROMPT,
|
|
28
|
+
actions,
|
|
29
|
+
provider,
|
|
30
|
+
ctx,
|
|
31
|
+
budget: 7, // ADR: Max 7 Tool-Calls pro Turn
|
|
32
|
+
});
|
|
33
|
+
let responseText = '';
|
|
34
|
+
for (;;) {
|
|
35
|
+
const { value, done } = await gen.next();
|
|
36
|
+
if (done)
|
|
37
|
+
break;
|
|
38
|
+
if (value.role === 'assistant' && typeof value.content === 'string') {
|
|
39
|
+
responseText = value.content;
|
|
40
|
+
}
|
|
41
|
+
// Bei ContentBlock[] den letzten Text extrahieren
|
|
42
|
+
if (value.role === 'assistant' && Array.isArray(value.content)) {
|
|
43
|
+
for (const block of value.content) {
|
|
44
|
+
if (block.type === 'text')
|
|
45
|
+
responseText = block.text;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const match = responseText.match(/\{[\s\S]*\}/);
|
|
51
|
+
if (!match)
|
|
52
|
+
return err('Cloud-Butler: No JSON in response');
|
|
53
|
+
const parsed = JSON.parse(match[0]);
|
|
54
|
+
return ok({
|
|
55
|
+
title: parsed.title ?? task.query,
|
|
56
|
+
summary: parsed.summary ?? '',
|
|
57
|
+
content: parsed.content ?? '',
|
|
58
|
+
confidence: parsed.confidence ?? 0.5,
|
|
59
|
+
sources: Array.isArray(parsed.sources) ? parsed.sources : [],
|
|
60
|
+
gaps: Array.isArray(parsed.gaps) ? parsed.gaps : [],
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return err('Cloud-Butler: Failed to parse response');
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=butler-cloud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butler-cloud.js","sourceRoot":"","sources":["../../src/compat/butler-cloud.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAA;AAC/C,OAAO,EAAE,EAAE,EAAE,GAAG,EAAe,MAAM,aAAa,CAAA;AAwBlD,MAAM,mBAAmB,GAAG;;;;+CAImB,CAAA;AAE/C,MAAM,UAAU,iBAAiB,CAC/B,QAAkB,EAClB,OAA0B,EAC1B,GAAY;IAEZ,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,aAAa;YAC/B,MAAM,OAAO,GAAG;gBACd,YAAY,IAAI,CAAC,IAAI,EAAE;gBACvB,UAAU,IAAI,CAAC,KAAK,EAAE;gBACtB,aAAa,CAAC,CAAC,CAAC,aAAa,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE;aAClD,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAE5B,MAAM,GAAG,GAAG,IAAI,CAAC;gBACf,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC9E,MAAM,EAAE,mBAAmB;gBAC3B,OAAO;gBACP,QAAQ;gBACR,GAAG;gBACH,MAAM,EAAE,CAAC,EAAG,iCAAiC;aAC9C,CAAC,CAAA;YAEF,IAAI,YAAY,GAAG,EAAE,CAAA;YACrB,SAAS,CAAC;gBACR,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;gBACxC,IAAI,IAAI;oBAAE,MAAK;gBACf,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBACpE,YAAY,GAAG,KAAK,CAAC,OAAO,CAAA;gBAC9B,CAAC;gBACD,kDAAkD;gBAClD,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC/D,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;wBAClC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;4BAAE,YAAY,GAAG,KAAK,CAAC,IAAI,CAAA;oBACtD,CAAC;gBACH,CAAC;YACH,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;gBAC/C,IAAI,CAAC,KAAK;oBAAE,OAAO,GAAG,CAAC,mCAAmC,CAAC,CAAA;gBAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAA4B,CAAA;gBAC9D,OAAO,EAAE,CAAC;oBACR,KAAK,EAAG,MAAM,CAAC,KAAgB,IAAI,IAAI,CAAC,KAAK;oBAC7C,OAAO,EAAG,MAAM,CAAC,OAAkB,IAAI,EAAE;oBACzC,OAAO,EAAG,MAAM,CAAC,OAAkB,IAAI,EAAE;oBACzC,UAAU,EAAG,MAAM,CAAC,UAAqB,IAAI,GAAG;oBAChD,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAmB,CAAC,CAAC,CAAC,EAAE;oBACxE,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAgB,CAAC,CAAC,CAAC,EAAE;iBAChE,CAAC,CAAA;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,CAAC,wCAAwC,CAAC,CAAA;YACtD,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT — Edge Butler Adapter
|
|
3
|
+
*
|
|
4
|
+
* Wraps Foundation Provider + Loop als EdgeButler Interface.
|
|
5
|
+
* Der Edge-Butler klassifiziert: IGNORE, OBSERVE, ROUTE_CLOUD, ALERT.
|
|
6
|
+
* Kein Chat, kein Draft — nur Routing + Gesture + Ledger-Eintrag.
|
|
7
|
+
*
|
|
8
|
+
* Messpunkt: Unter 100 Zeilen = Interfaces stimmen.
|
|
9
|
+
*/
|
|
10
|
+
import type { Provider } from '../s10-inference/provider.js';
|
|
11
|
+
import type { Context } from '../s10-inference/context.js';
|
|
12
|
+
import type { GestureType } from '../s05-rendering/types.js';
|
|
13
|
+
import { type Result } from '../types.js';
|
|
14
|
+
export type EdgeIntent = 'ignore' | 'observe' | 'route_cloud' | 'alert';
|
|
15
|
+
export type EdgeInput = {
|
|
16
|
+
triggeredKeyword?: string;
|
|
17
|
+
ledgerSnapshot: string;
|
|
18
|
+
roomContext: {
|
|
19
|
+
roomId: string;
|
|
20
|
+
participants: string[];
|
|
21
|
+
activeSpeaker?: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type EdgeOutput = {
|
|
25
|
+
intent: EdgeIntent;
|
|
26
|
+
gesture?: GestureType;
|
|
27
|
+
ledgerEntry?: string;
|
|
28
|
+
cloudQuery?: string;
|
|
29
|
+
};
|
|
30
|
+
export type EdgeButler = {
|
|
31
|
+
process(input: EdgeInput): Promise<Result<EdgeOutput, string>>;
|
|
32
|
+
};
|
|
33
|
+
export declare function createEdgeButler(provider: Provider, ctx: Context): EdgeButler;
|
|
34
|
+
//# sourceMappingURL=butler-edge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butler-edge.d.ts","sourceRoot":"","sources":["../../src/compat/butler-edge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAE5D,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAElD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,CAAA;AAEvE,MAAM,MAAM,SAAS,GAAG;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE;QACX,MAAM,EAAE,MAAM,CAAA;QACd,YAAY,EAAE,MAAM,EAAE,CAAA;QACtB,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;CACF,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAA;CAC/D,CAAA;AASD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,GAAG,UAAU,CA2C7E"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT — Edge Butler Adapter
|
|
3
|
+
*
|
|
4
|
+
* Wraps Foundation Provider + Loop als EdgeButler Interface.
|
|
5
|
+
* Der Edge-Butler klassifiziert: IGNORE, OBSERVE, ROUTE_CLOUD, ALERT.
|
|
6
|
+
* Kein Chat, kein Draft — nur Routing + Gesture + Ledger-Eintrag.
|
|
7
|
+
*
|
|
8
|
+
* Messpunkt: Unter 100 Zeilen = Interfaces stimmen.
|
|
9
|
+
*/
|
|
10
|
+
import { loop } from '../s10-inference/loop.js';
|
|
11
|
+
import { ok, err } from '../types.js';
|
|
12
|
+
const EDGE_SYSTEM_PROMPT = `Du bist Sebastian-Innen, ein Edge-Classifier.
|
|
13
|
+
Antworte NUR als JSON: {"intent":"ignore"|"observe"|"route_cloud"|"alert","gesture":"idle"|"nodding"|"bowing"|"hand_raise","ledgerEntry":"...oder null","cloudQuery":"...oder null"}
|
|
14
|
+
Kein Fließtext. Kein Markdown. Nur JSON.
|
|
15
|
+
Wenn Stichwort erkannt → intent: route_cloud, cloudQuery formulieren.
|
|
16
|
+
Wenn nichts relevant → intent: ignore.
|
|
17
|
+
Max 150 Zeichen für ledgerEntry.`;
|
|
18
|
+
export function createEdgeButler(provider, ctx) {
|
|
19
|
+
return {
|
|
20
|
+
async process(input) {
|
|
21
|
+
const userMsg = [
|
|
22
|
+
input.triggeredKeyword ? `Stichwort: "${input.triggeredKeyword}"` : '',
|
|
23
|
+
`Raum: ${input.roomContext.roomId}, ${input.roomContext.participants.length} Teilnehmer`,
|
|
24
|
+
input.roomContext.activeSpeaker ? `Spricht: ${input.roomContext.activeSpeaker}` : '',
|
|
25
|
+
`Ledger:\n${input.ledgerSnapshot}`,
|
|
26
|
+
].filter(Boolean).join('\n');
|
|
27
|
+
const gen = loop({
|
|
28
|
+
messages: [{ id: 'edge-in', role: 'user', content: userMsg, ts: Date.now() }],
|
|
29
|
+
system: EDGE_SYSTEM_PROMPT,
|
|
30
|
+
actions: [],
|
|
31
|
+
provider,
|
|
32
|
+
ctx,
|
|
33
|
+
budget: 1,
|
|
34
|
+
});
|
|
35
|
+
let responseText = '';
|
|
36
|
+
for (;;) {
|
|
37
|
+
const { value, done } = await gen.next();
|
|
38
|
+
if (done)
|
|
39
|
+
break;
|
|
40
|
+
if (value.role === 'assistant' && typeof value.content === 'string') {
|
|
41
|
+
responseText = value.content;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const match = responseText.match(/\{[\s\S]*\}/);
|
|
46
|
+
if (!match)
|
|
47
|
+
return err('Edge-Butler: No JSON in response');
|
|
48
|
+
const parsed = JSON.parse(match[0]);
|
|
49
|
+
return ok({
|
|
50
|
+
intent: parsed.intent ?? 'ignore',
|
|
51
|
+
gesture: parsed.gesture ?? 'idle',
|
|
52
|
+
ledgerEntry: parsed.ledgerEntry,
|
|
53
|
+
cloudQuery: parsed.cloudQuery,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return err('Edge-Butler: Failed to parse response');
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=butler-edge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butler-edge.js","sourceRoot":"","sources":["../../src/compat/butler-edge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAA;AAC/C,OAAO,EAAE,EAAE,EAAE,GAAG,EAAe,MAAM,aAAa,CAAA;AAyBlD,MAAM,kBAAkB,GAAG;;;;;iCAKM,CAAA;AAEjC,MAAM,UAAU,gBAAgB,CAAC,QAAkB,EAAE,GAAY;IAC/D,OAAO;QACL,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,MAAM,OAAO,GAAG;gBACd,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,KAAK,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,EAAE;gBACtE,SAAS,KAAK,CAAC,WAAW,CAAC,MAAM,KAAK,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC,MAAM,aAAa;gBACxF,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE;gBACpF,YAAY,KAAK,CAAC,cAAc,EAAE;aACnC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAE5B,MAAM,GAAG,GAAG,IAAI,CAAC;gBACf,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;gBAC7E,MAAM,EAAE,kBAAkB;gBAC1B,OAAO,EAAE,EAAE;gBACX,QAAQ;gBACR,GAAG;gBACH,MAAM,EAAE,CAAC;aACV,CAAC,CAAA;YAEF,IAAI,YAAY,GAAG,EAAE,CAAA;YACrB,SAAS,CAAC;gBACR,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;gBACxC,IAAI,IAAI;oBAAE,MAAK;gBACf,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;oBACpE,YAAY,GAAG,KAAK,CAAC,OAAO,CAAA;gBAC9B,CAAC;YACH,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;gBAC/C,IAAI,CAAC,KAAK;oBAAE,OAAO,GAAG,CAAC,kCAAkC,CAAC,CAAA;gBAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAA4B,CAAA;gBAC9D,OAAO,EAAE,CAAC;oBACR,MAAM,EAAG,MAAM,CAAC,MAAqB,IAAI,QAAQ;oBACjD,OAAO,EAAG,MAAM,CAAC,OAAuB,IAAI,MAAM;oBAClD,WAAW,EAAE,MAAM,CAAC,WAAiC;oBACrD,UAAU,EAAE,MAAM,CAAC,UAAgC;iBACpD,CAAC,CAAA;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,CAAC,uCAAuC,CAAC,CAAA;YACrD,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT — Butler Pair Factory
|
|
3
|
+
*
|
|
4
|
+
* Erzeugt Edge + Cloud Butler Paar mit SharedDoc für State-Sync.
|
|
5
|
+
* Ein Aufruf, alles verdrahtet.
|
|
6
|
+
*/
|
|
7
|
+
import type { Provider } from '../s10-inference/provider.js';
|
|
8
|
+
import type { Action } from '../s10-inference/action.js';
|
|
9
|
+
import { type Context, type GateMode } from '../s10-inference/context.js';
|
|
10
|
+
import type { SharedDocWithAccessors } from '../s02-crdt/types.js';
|
|
11
|
+
import { type EdgeButler } from './butler-edge.js';
|
|
12
|
+
import { type CloudButler } from './butler-cloud.js';
|
|
13
|
+
export type ButlerPair = {
|
|
14
|
+
edge: EdgeButler;
|
|
15
|
+
cloud: CloudButler;
|
|
16
|
+
shared: SharedDocWithAccessors;
|
|
17
|
+
edgeCtx: Context;
|
|
18
|
+
cloudCtx: Context;
|
|
19
|
+
};
|
|
20
|
+
export declare function createButlerPair(opts: {
|
|
21
|
+
edgeProvider: Provider;
|
|
22
|
+
cloudProvider: Provider;
|
|
23
|
+
cloudActions?: readonly Action[];
|
|
24
|
+
root: string;
|
|
25
|
+
mode?: GateMode;
|
|
26
|
+
}): ButlerPair;
|
|
27
|
+
//# sourceMappingURL=butler-pair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butler-pair.d.ts","sourceRoot":"","sources":["../../src/compat/butler-pair.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAiB,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAExF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAClE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACpE,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEvE,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,sBAAsB,CAAA;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,YAAY,EAAE,QAAQ,CAAA;IACtB,aAAa,EAAE,QAAQ,CAAA;IACvB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB,GAAG,UAAU,CAYb"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT — Butler Pair Factory
|
|
3
|
+
*
|
|
4
|
+
* Erzeugt Edge + Cloud Butler Paar mit SharedDoc für State-Sync.
|
|
5
|
+
* Ein Aufruf, alles verdrahtet.
|
|
6
|
+
*/
|
|
7
|
+
import { createContext } from '../s10-inference/context.js';
|
|
8
|
+
import { createYjsDoc } from '../s02-crdt/yjs.js';
|
|
9
|
+
import { createEdgeButler } from './butler-edge.js';
|
|
10
|
+
import { createCloudButler } from './butler-cloud.js';
|
|
11
|
+
export function createButlerPair(opts) {
|
|
12
|
+
const shared = createYjsDoc();
|
|
13
|
+
const edgeCtx = createContext({ model: 'edge', root: opts.root, mode: opts.mode });
|
|
14
|
+
const cloudCtx = createContext({ model: 'cloud', root: opts.root, mode: opts.mode });
|
|
15
|
+
return {
|
|
16
|
+
edge: createEdgeButler(opts.edgeProvider, edgeCtx),
|
|
17
|
+
cloud: createCloudButler(opts.cloudProvider, opts.cloudActions ?? [], cloudCtx),
|
|
18
|
+
shared,
|
|
19
|
+
edgeCtx,
|
|
20
|
+
cloudCtx,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=butler-pair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"butler-pair.js","sourceRoot":"","sources":["../../src/compat/butler-pair.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,aAAa,EAA+B,MAAM,6BAA6B,CAAA;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,OAAO,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAoB,MAAM,mBAAmB,CAAA;AAUvE,MAAM,UAAU,gBAAgB,CAAC,IAMhC;IACC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAA;IAC7B,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IAClF,MAAM,QAAQ,GAAG,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;IAEpF,OAAO;QACL,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC;QAClD,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,YAAY,IAAI,EAAE,EAAE,QAAQ,CAAC;QAC/E,MAAM;QACN,OAAO;QACP,QAAQ;KACT,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPAT — Entry ↔ LedgerEntry Adapter
|
|
3
|
+
*
|
|
4
|
+
* Lebt in compat/, NICHT in touches/ oder sXX/.
|
|
5
|
+
* compat/ ist die Brücke zu externen Typsystemen.
|
|
6
|
+
* Foundation kennt keine externen Types.
|
|
7
|
+
* Dieser Adapter kennt beide Seiten.
|
|
8
|
+
*
|
|
9
|
+
* Observer-Korrektur #1: Klare Positionierung außerhalb des Schichten-Modells.
|
|
10
|
+
*/
|
|
11
|
+
import type { Entry } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* 0room0's LedgerEntry Type (gespiegelt, nicht importiert).
|
|
14
|
+
* Foundation importiert NICHT aus 0room0. Die Struktur wird hier definiert.
|
|
15
|
+
*/
|
|
16
|
+
export type LedgerEntry = {
|
|
17
|
+
text: string;
|
|
18
|
+
timestamp: Date;
|
|
19
|
+
participants: string[];
|
|
20
|
+
category: string;
|
|
21
|
+
sessionId: string;
|
|
22
|
+
embedding?: Float32Array;
|
|
23
|
+
};
|
|
24
|
+
export declare function ledgerToEntry(ledger: LedgerEntry): Entry;
|
|
25
|
+
export declare function entryToLedger(entry: Entry): LedgerEntry;
|
|
26
|
+
//# sourceMappingURL=entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entry.d.ts","sourceRoot":"","sources":["../../src/compat/entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAA;AAEvD;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,IAAI,CAAA;IACf,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,YAAY,CAAA;CACzB,CAAA;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAWxD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW,CAUvD"}
|