@peac/adapter-openclaw 0.10.10 → 0.10.12
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 +120 -118
- package/dist/activate.d.ts +87 -0
- package/dist/activate.d.ts.map +1 -0
- package/dist/index.cjs +341 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +319 -67
- package/dist/index.mjs.map +1 -1
- package/dist/keygen-cli.cjs +116 -0
- package/dist/keygen-cli.cjs.map +1 -0
- package/dist/keygen-cli.d.ts +7 -0
- package/dist/keygen-cli.d.ts.map +1 -0
- package/dist/keygen-cli.mjs +93 -0
- package/dist/keygen-cli.mjs.map +1 -0
- package/dist/keygen.d.ts +53 -0
- package/dist/keygen.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/tools.d.ts +5 -1
- package/dist/tools.d.ts.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +11 -7
package/README.md
CHANGED
|
@@ -1,82 +1,122 @@
|
|
|
1
1
|
# @peac/adapter-openclaw
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Offline-verifiable activity records for OpenClaw sessions.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { activate, generateSigningKey } from '@peac/adapter-openclaw';
|
|
9
|
+
|
|
10
|
+
// Generate a signing key (one-time setup)
|
|
11
|
+
const key = await generateSigningKey({ outputDir: '.peac' });
|
|
12
|
+
|
|
13
|
+
// Activate the plugin
|
|
14
|
+
const plugin = await activate({
|
|
15
|
+
config: {
|
|
16
|
+
signing: {
|
|
17
|
+
key_ref: `file:${key.keyPath}`,
|
|
18
|
+
issuer: 'https://my-org.example.com',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
plugin.instance.start();
|
|
24
|
+
// Records are now captured automatically via hooks.
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> Never log or print the contents of `key_ref`. Use `env:` key references in CI, `file:` for local development. Signing key files are written with 0600 permissions (owner read/write only).
|
|
28
|
+
|
|
29
|
+
## What It Records
|
|
6
30
|
|
|
7
|
-
|
|
31
|
+
Every tool call your agent makes is captured as a tamper-evident record:
|
|
8
32
|
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **Tailer**: Session history fallback for resilience
|
|
33
|
+
- **Tool name, timing, status** -- what ran, when, whether it succeeded
|
|
34
|
+
- **Input/output digests** -- SHA-256 hashes by default (payloads are never stored in plaintext unless you explicitly allowlist a tool)
|
|
35
|
+
- **Chain linkage** -- each record links to the previous one, so gaps or reordering are detectable
|
|
13
36
|
|
|
14
|
-
|
|
37
|
+
Records are signed with your key and written to disk as individual `.peac.json` files.
|
|
38
|
+
|
|
39
|
+
## Commands
|
|
40
|
+
|
|
41
|
+
### Key Generation
|
|
15
42
|
|
|
16
43
|
```bash
|
|
17
|
-
|
|
44
|
+
npx peac-keygen --output-dir .peac
|
|
18
45
|
```
|
|
19
46
|
|
|
20
|
-
|
|
47
|
+
Generates a signing keypair. The private key is written with 0600 permissions. Print the `kid` and public key for registration with your infrastructure.
|
|
21
48
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
import { createHookHandler, mapToolCallEvent } from '@peac/adapter-openclaw';
|
|
26
|
-
|
|
27
|
-
// Create a capture session
|
|
28
|
-
const session = createCaptureSession({
|
|
29
|
-
store: createInMemorySpoolStore(),
|
|
30
|
-
dedupe: createInMemoryDedupeIndex(),
|
|
31
|
-
hasher: createHasher(),
|
|
32
|
-
});
|
|
49
|
+
### Plugin Tools
|
|
50
|
+
|
|
51
|
+
The plugin exposes 4 tools to the agent:
|
|
33
52
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
53
|
+
| Tool | Description |
|
|
54
|
+
| ----------------------------- | ----------------------------------------------------------------- |
|
|
55
|
+
| `peac_receipts.status` | Spool size, last receipt time, configuration summary |
|
|
56
|
+
| `peac_receipts.export_bundle` | Export receipts as an evidence bundle (manifest.json + receipts/) |
|
|
57
|
+
| `peac_receipts.verify` | Verify a receipt or bundle offline |
|
|
58
|
+
| `peac_receipts.query` | Query receipts by workflow ID, tool name, or time range |
|
|
59
|
+
|
|
60
|
+
## Configuration
|
|
61
|
+
|
|
62
|
+
### `activate()` Options
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
const plugin = await activate({
|
|
37
66
|
config: {
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
signing: {
|
|
68
|
+
key_ref: 'env:PEAC_SIGNING_KEY', // or 'file:/path/to/key.jwk'
|
|
69
|
+
issuer: 'https://my-org.example.com',
|
|
70
|
+
audience: 'https://api.example.com', // optional
|
|
71
|
+
},
|
|
72
|
+
output_dir: '.peac/receipts', // optional (default: {dataDir}/receipts/)
|
|
73
|
+
background: {
|
|
74
|
+
drain_interval_ms: 1000, // optional (default: 1000)
|
|
75
|
+
batch_size: 100, // optional (default: 100)
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
dataDir: '.peac', // optional (default: ~/.openclaw/peac/)
|
|
79
|
+
spoolOptions: {
|
|
80
|
+
maxEntries: 100_000, // optional (default: 100,000)
|
|
81
|
+
maxFileBytes: 104_857_600, // optional (default: 100MB)
|
|
82
|
+
autoCommitIntervalMs: 5000, // optional (default: 5000, 0 to disable)
|
|
40
83
|
},
|
|
41
84
|
});
|
|
85
|
+
```
|
|
42
86
|
|
|
43
|
-
|
|
44
|
-
const result = await handler.afterToolCall({
|
|
45
|
-
tool_call_id: 'call_123',
|
|
46
|
-
run_id: 'run_abc',
|
|
47
|
-
tool_name: 'web_search',
|
|
48
|
-
started_at: '2024-02-01T10:00:00Z',
|
|
49
|
-
completed_at: '2024-02-01T10:00:01Z',
|
|
50
|
-
status: 'ok',
|
|
51
|
-
input: { query: 'hello world' },
|
|
52
|
-
output: { results: ['result1'] },
|
|
53
|
-
});
|
|
87
|
+
### Key Reference Schemes
|
|
54
88
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
89
|
+
| Scheme | Format | Use Case |
|
|
90
|
+
| ------- | ----------------------- | ---------------------------------------------- |
|
|
91
|
+
| `env:` | `env:PEAC_SIGNING_KEY` | CI/CD, containers (key in env var as JWK JSON) |
|
|
92
|
+
| `file:` | `file:/path/to/key.jwk` | Local development (key file on disk) |
|
|
58
93
|
|
|
59
|
-
|
|
60
|
-
|
|
94
|
+
## Compatibility
|
|
95
|
+
|
|
96
|
+
| Requirement | Value |
|
|
97
|
+
| ------------- | ---------------------------------------------------------- |
|
|
98
|
+
| Node.js | >= 22.0.0 |
|
|
99
|
+
| Module format | ESM (`.mjs`) and CJS (`.cjs`) dual-published |
|
|
100
|
+
| Runtime | Node.js only (uses `fs`, `path`, `crypto`) |
|
|
101
|
+
| Workers/Edge | Not supported (requires file system access) |
|
|
102
|
+
| OpenClaw | v2026.2.7+ (before_tool_call or tool_result_persist hooks) |
|
|
61
103
|
|
|
62
104
|
## Architecture
|
|
63
105
|
|
|
64
106
|
### Two-Stage Pipeline
|
|
65
107
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
108
|
+
```text
|
|
109
|
+
Tool Call Spool Receipts
|
|
110
|
+
(sync hook) --> (append-only) --> (signed receipt)
|
|
111
|
+
< 10ms spool.jsonl *.peac.json
|
|
112
|
+
```
|
|
70
113
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- Convert to `InteractionEvidenceV01`
|
|
74
|
-
- Sign with configured key
|
|
75
|
-
- Write receipt to output
|
|
114
|
+
1. **Capture stage** (sync, < 10ms target): Map OpenClaw event to a captured action, hash payloads inline, write to tamper-evident spool
|
|
115
|
+
2. **Emit stage** (async background): Drain spool periodically, convert to interaction evidence, sign with configured key, write receipt to output directory
|
|
76
116
|
|
|
77
|
-
### OpenClaw
|
|
117
|
+
### OpenClaw-to-Receipt Mapping
|
|
78
118
|
|
|
79
|
-
| OpenClaw Concept |
|
|
119
|
+
| OpenClaw Concept | Receipt Field |
|
|
80
120
|
| --------------------- | --------------------------- |
|
|
81
121
|
| Session key | `workflow_id` (correlation) |
|
|
82
122
|
| Run ID + tool_call_id | `interaction_id` (dedupe) |
|
|
@@ -88,85 +128,47 @@ await handler.close();
|
|
|
88
128
|
|
|
89
129
|
## API Reference
|
|
90
130
|
|
|
91
|
-
###
|
|
92
|
-
|
|
93
|
-
```typescript
|
|
94
|
-
import { mapToolCallEvent, mapToolCallEventBatch } from '@peac/adapter-openclaw';
|
|
95
|
-
|
|
96
|
-
// Map single event
|
|
97
|
-
const result = mapToolCallEvent(event, config);
|
|
98
|
-
if (result.success) {
|
|
99
|
-
console.log(result.action);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Map batch
|
|
103
|
-
const results = mapToolCallEventBatch(events, config);
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Hook Handler
|
|
131
|
+
### High-Level (Recommended)
|
|
107
132
|
|
|
108
133
|
```typescript
|
|
109
|
-
import {
|
|
134
|
+
import { activate, generateSigningKey } from '@peac/adapter-openclaw';
|
|
110
135
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
onCapture: (result, event) => {
|
|
115
|
-
console.log('Captured:', result);
|
|
116
|
-
},
|
|
117
|
-
});
|
|
136
|
+
// activate() wires all components from config
|
|
137
|
+
const plugin = await activate(options);
|
|
138
|
+
plugin.instance.start();
|
|
118
139
|
|
|
119
|
-
//
|
|
120
|
-
await
|
|
140
|
+
// Capture events via the hook handler
|
|
141
|
+
await plugin.hookHandler.afterToolCall(event);
|
|
121
142
|
|
|
122
|
-
//
|
|
123
|
-
await
|
|
143
|
+
// Flush pending records into signed receipts
|
|
144
|
+
await plugin.flush();
|
|
124
145
|
|
|
125
|
-
//
|
|
126
|
-
await
|
|
146
|
+
// Clean shutdown (flushes + closes stores)
|
|
147
|
+
await plugin.shutdown();
|
|
127
148
|
```
|
|
128
149
|
|
|
129
|
-
###
|
|
150
|
+
### Lower-Level (Advanced)
|
|
130
151
|
|
|
131
|
-
|
|
132
|
-
import { createReceiptEmitter, createBackgroundService } from '@peac/adapter-openclaw';
|
|
133
|
-
|
|
134
|
-
const emitter = createReceiptEmitter({
|
|
135
|
-
signer,
|
|
136
|
-
writer,
|
|
137
|
-
config: { platform: 'openclaw' },
|
|
138
|
-
});
|
|
152
|
+
For custom wiring or when you need direct access to individual components:
|
|
139
153
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// ... later
|
|
149
|
-
service.stop();
|
|
154
|
+
```typescript
|
|
155
|
+
import {
|
|
156
|
+
createHookHandler,
|
|
157
|
+
createReceiptEmitter,
|
|
158
|
+
createBackgroundService,
|
|
159
|
+
mapToolCallEvent,
|
|
160
|
+
createSessionHistoryTailer,
|
|
161
|
+
} from '@peac/adapter-openclaw';
|
|
150
162
|
```
|
|
151
163
|
|
|
152
|
-
|
|
164
|
+
See the source for `createHookHandler()`, `createReceiptEmitter()`, `createBackgroundService()`, and `createSessionHistoryTailer()`.
|
|
153
165
|
|
|
154
|
-
|
|
155
|
-
import { createSessionHistoryTailer } from '@peac/adapter-openclaw';
|
|
166
|
+
## Security
|
|
156
167
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return openclaw.sessions.getHistory(sessionId, { after: afterEventId });
|
|
162
|
-
},
|
|
163
|
-
pollIntervalMs: 1000,
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
tailer.start();
|
|
167
|
-
// ... later
|
|
168
|
-
tailer.stop();
|
|
169
|
-
```
|
|
168
|
+
- **Privacy by default**: All inputs and outputs are hashed (SHA-256). Plaintext is only captured for explicitly allowlisted tools.
|
|
169
|
+
- **Key protection**: Signing key files are written with 0600 permissions. Use `env:` references in CI to avoid keys on disk.
|
|
170
|
+
- **Tamper evidence**: Each spool entry links to the previous via digest. Gaps or reordering are detectable.
|
|
171
|
+
- **No secret logging**: The adapter never logs private key material. Only the key ID (`kid`) and public key component appear in logs.
|
|
170
172
|
|
|
171
173
|
## Error Codes
|
|
172
174
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @peac/adapter-openclaw - Plugin Activation
|
|
3
|
+
*
|
|
4
|
+
* High-level entry point that wires together all adapter components
|
|
5
|
+
* from config. Calls existing functions (resolveSigner, createPluginInstance,
|
|
6
|
+
* createFileReceiptWriter, etc.) -- no logic duplication.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* const result = await activate({ config, logger });
|
|
10
|
+
* result.instance.start();
|
|
11
|
+
*
|
|
12
|
+
* When OpenClaw's plugin loader gains a stable activation shape,
|
|
13
|
+
* add a thin validated wrapper at that time.
|
|
14
|
+
*/
|
|
15
|
+
import type { OpenClawAdapterConfig } from './types.js';
|
|
16
|
+
import type { PluginLogger, PluginInstance, PluginTool } from './plugin.js';
|
|
17
|
+
import type { OpenClawHookHandler } from './hooks.js';
|
|
18
|
+
import type { FsSpoolStoreOptions } from '@peac/capture-node';
|
|
19
|
+
/**
|
|
20
|
+
* Options for activating the plugin.
|
|
21
|
+
*/
|
|
22
|
+
export interface ActivateOptions {
|
|
23
|
+
/** Adapter configuration (signing, capture, correlation, background). */
|
|
24
|
+
config: ActivateConfig;
|
|
25
|
+
/** Logger instance. */
|
|
26
|
+
logger?: PluginLogger;
|
|
27
|
+
/** Data directory for spool, dedupe, and signing key. Default: ~/.openclaw/peac/ */
|
|
28
|
+
dataDir?: string;
|
|
29
|
+
/** Spool store options override. */
|
|
30
|
+
spoolOptions?: Partial<Pick<FsSpoolStoreOptions, 'maxEntries' | 'maxFileBytes' | 'autoCommitIntervalMs' | 'lockOptions'>>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Configuration for activate(). Extends OpenClawAdapterConfig with
|
|
34
|
+
* required signing fields.
|
|
35
|
+
*/
|
|
36
|
+
export interface ActivateConfig extends OpenClawAdapterConfig {
|
|
37
|
+
/** Signing configuration (required for activation). */
|
|
38
|
+
signing: {
|
|
39
|
+
/** Key reference: env:VAR_NAME or file:/path */
|
|
40
|
+
key_ref: string;
|
|
41
|
+
/** Issuer URI for receipts */
|
|
42
|
+
issuer: string;
|
|
43
|
+
/** Optional audience URI */
|
|
44
|
+
audience?: string;
|
|
45
|
+
};
|
|
46
|
+
/** Output directory for receipt files. Default: {dataDir}/receipts/ */
|
|
47
|
+
output_dir?: string;
|
|
48
|
+
/** Background emitter settings. */
|
|
49
|
+
background?: {
|
|
50
|
+
drain_interval_ms?: number;
|
|
51
|
+
batch_size?: number;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Result of activating the plugin.
|
|
56
|
+
*/
|
|
57
|
+
export interface ActivateResult {
|
|
58
|
+
/** The running plugin instance. */
|
|
59
|
+
instance: PluginInstance;
|
|
60
|
+
/** The 4 plugin tools (status, export, verify, query). */
|
|
61
|
+
tools: PluginTool[];
|
|
62
|
+
/** Hook handler for tool call events. */
|
|
63
|
+
hookHandler: OpenClawHookHandler;
|
|
64
|
+
/** Data directory used. */
|
|
65
|
+
dataDir: string;
|
|
66
|
+
/** Flush pending spool entries into signed receipts. */
|
|
67
|
+
flush: () => Promise<void>;
|
|
68
|
+
/** Shut down the plugin cleanly. */
|
|
69
|
+
shutdown: () => Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Activate the PEAC evidence export plugin.
|
|
73
|
+
*
|
|
74
|
+
* This is the single canonical entry point. It:
|
|
75
|
+
* 1. Resolves the signing key from config (env: or file:)
|
|
76
|
+
* 2. Creates durable stores (FsSpoolStore + FsDedupeIndex)
|
|
77
|
+
* 3. Creates the receipt writer
|
|
78
|
+
* 4. Creates the plugin instance (session + hooks + emitter)
|
|
79
|
+
* 5. Creates the 4 plugin tools
|
|
80
|
+
* 6. Logs startup diagnostics
|
|
81
|
+
*
|
|
82
|
+
* @throws If signing key cannot be resolved
|
|
83
|
+
* @throws If data directory is not writable
|
|
84
|
+
* @throws If spool lockfile cannot be acquired
|
|
85
|
+
*/
|
|
86
|
+
export declare function activate(options: ActivateOptions): Promise<ActivateResult>;
|
|
87
|
+
//# sourceMappingURL=activate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activate.d.ts","sourceRoot":"","sources":["../src/activate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAc9D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,MAAM,EAAE,cAAc,CAAC;IACvB,uBAAuB;IACvB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,YAAY,CAAC,EAAE,OAAO,CACpB,IAAI,CACF,mBAAmB,EACnB,YAAY,GAAG,cAAc,GAAG,sBAAsB,GAAG,aAAa,CACvE,CACF,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,cAAe,SAAQ,qBAAqB;IAC3D,uDAAuD;IACvD,OAAO,EAAE;QACP,gDAAgD;QAChD,OAAO,EAAE,MAAM,CAAC;QAChB,8BAA8B;QAC9B,MAAM,EAAE,MAAM,CAAC;QACf,4BAA4B;QAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,UAAU,CAAC,EAAE;QACX,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,QAAQ,EAAE,cAAc,CAAC;IACzB,0DAA0D;IAC1D,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,yCAAyC;IACzC,WAAW,EAAE,mBAAmB,CAAC;IACjC,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,oCAAoC;IACpC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AA4BD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8FhF"}
|