@peac/adapter-openclaw 0.10.7
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 +190 -0
- package/dist/emitter.d.ts +129 -0
- package/dist/emitter.d.ts.map +1 -0
- package/dist/emitter.js +197 -0
- package/dist/emitter.js.map +1 -0
- package/dist/hooks.d.ts +112 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +157 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/mapper.d.ts +33 -0
- package/dist/mapper.d.ts.map +1 -0
- package/dist/mapper.js +320 -0
- package/dist/mapper.js.map +1 -0
- package/dist/plugin.d.ts +213 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +331 -0
- package/dist/plugin.js.map +1 -0
- package/dist/tools.d.ts +45 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +732 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +221 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +57 -0
- package/dist/types.js.map +1 -0
- package/openclaw.plugin.json +117 -0
- package/package.json +46 -0
- package/skills/peac/SKILL.md +172 -0
package/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# @peac/adapter-openclaw
|
|
2
|
+
|
|
3
|
+
OpenClaw adapter for PEAC interaction evidence capture.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@peac/adapter-openclaw` provides a complete capture pipeline for recording OpenClaw tool calls as PEAC interaction evidence. It includes:
|
|
8
|
+
|
|
9
|
+
- **Mapper**: OpenClaw tool call events -> PEAC `CapturedAction`
|
|
10
|
+
- **Hooks**: Sync capture bindings (< 10ms target)
|
|
11
|
+
- **Emitter**: Background receipt signing and persistence
|
|
12
|
+
- **Tailer**: Session history fallback for resilience
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add @peac/adapter-openclaw
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { createCaptureSession, createHasher } from '@peac/capture-core';
|
|
24
|
+
import { createInMemorySpoolStore, createInMemoryDedupeIndex } from '@peac/capture-core/testkit';
|
|
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
|
+
});
|
|
33
|
+
|
|
34
|
+
// Create a hook handler
|
|
35
|
+
const handler = createHookHandler({
|
|
36
|
+
session,
|
|
37
|
+
config: {
|
|
38
|
+
platform: 'openclaw',
|
|
39
|
+
platform_version: '0.2.0',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Handle OpenClaw tool call events
|
|
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
|
+
});
|
|
54
|
+
|
|
55
|
+
if (result.success) {
|
|
56
|
+
console.log('Captured:', result.entry.entry_digest);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
await handler.close();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Architecture
|
|
63
|
+
|
|
64
|
+
### Two-Stage Pipeline
|
|
65
|
+
|
|
66
|
+
1. **Capture Stage** (sync, < 10ms target)
|
|
67
|
+
- Map OpenClaw event to `CapturedAction`
|
|
68
|
+
- Hash payloads inline (truncate large payloads)
|
|
69
|
+
- Write to tamper-evident spool
|
|
70
|
+
|
|
71
|
+
2. **Emit Stage** (async background)
|
|
72
|
+
- Drain spool periodically
|
|
73
|
+
- Convert to `InteractionEvidenceV01`
|
|
74
|
+
- Sign with configured key
|
|
75
|
+
- Write receipt to output
|
|
76
|
+
|
|
77
|
+
### OpenClaw to PEAC Mapping
|
|
78
|
+
|
|
79
|
+
| OpenClaw Concept | PEAC Location |
|
|
80
|
+
| --------------------- | --------------------------- |
|
|
81
|
+
| Session key | `workflow_id` (correlation) |
|
|
82
|
+
| Run ID + tool_call_id | `interaction_id` (dedupe) |
|
|
83
|
+
| Tool call params | `input.digest` |
|
|
84
|
+
| Tool call result | `output.digest` |
|
|
85
|
+
| Tool name | `tool.name` |
|
|
86
|
+
| Sandbox mode | `policy.sandbox_enabled` |
|
|
87
|
+
| Elevated flag | `policy.elevated` |
|
|
88
|
+
|
|
89
|
+
## API Reference
|
|
90
|
+
|
|
91
|
+
### Mapper
|
|
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
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
import { createHookHandler, captureBatch, captureParallel } from '@peac/adapter-openclaw';
|
|
110
|
+
|
|
111
|
+
const handler = createHookHandler({
|
|
112
|
+
session,
|
|
113
|
+
config: { platform: 'openclaw' },
|
|
114
|
+
onCapture: (result, event) => {
|
|
115
|
+
console.log('Captured:', result);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Single event
|
|
120
|
+
await handler.afterToolCall(event);
|
|
121
|
+
|
|
122
|
+
// Batch (sequential)
|
|
123
|
+
await captureBatch(handler, events);
|
|
124
|
+
|
|
125
|
+
// Batch (parallel - non-deterministic order)
|
|
126
|
+
await captureParallel(handler, events);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Background Emitter
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { createReceiptEmitter, createBackgroundService } from '@peac/adapter-openclaw';
|
|
133
|
+
|
|
134
|
+
const emitter = createReceiptEmitter({
|
|
135
|
+
signer,
|
|
136
|
+
writer,
|
|
137
|
+
config: { platform: 'openclaw' },
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const service = createBackgroundService({
|
|
141
|
+
emitter,
|
|
142
|
+
getPendingEntries: () => spoolStore.getPending(),
|
|
143
|
+
markEmitted: (digest) => dedupeIndex.markEmitted(digest),
|
|
144
|
+
drainIntervalMs: 1000,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
service.start();
|
|
148
|
+
// ... later
|
|
149
|
+
service.stop();
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Session History Tailer (Fallback)
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
import { createSessionHistoryTailer } from '@peac/adapter-openclaw';
|
|
156
|
+
|
|
157
|
+
const tailer = createSessionHistoryTailer({
|
|
158
|
+
handler,
|
|
159
|
+
sessionId: 'session_123',
|
|
160
|
+
fetchHistory: async (sessionId, afterEventId) => {
|
|
161
|
+
return openclaw.sessions.getHistory(sessionId, { after: afterEventId });
|
|
162
|
+
},
|
|
163
|
+
pollIntervalMs: 1000,
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
tailer.start();
|
|
167
|
+
// ... later
|
|
168
|
+
tailer.stop();
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Error Codes
|
|
172
|
+
|
|
173
|
+
| Code | Description |
|
|
174
|
+
| --------------------------------- | ------------------------------- |
|
|
175
|
+
| `E_OPENCLAW_MISSING_FIELD` | Required field missing in event |
|
|
176
|
+
| `E_OPENCLAW_INVALID_FIELD` | Invalid field value in event |
|
|
177
|
+
| `E_OPENCLAW_SERIALIZATION_FAILED` | Payload serialization failed |
|
|
178
|
+
| `E_OPENCLAW_SIGNING_FAILED` | Receipt signing failed |
|
|
179
|
+
|
|
180
|
+
## Warning Codes
|
|
181
|
+
|
|
182
|
+
| Code | Description |
|
|
183
|
+
| ----------------------------------- | --------------------------- |
|
|
184
|
+
| `W_OPENCLAW_PAYLOAD_TRUNCATED` | Payload exceeded size limit |
|
|
185
|
+
| `W_OPENCLAW_OPTIONAL_FIELD_MISSING` | Optional field missing |
|
|
186
|
+
| `W_OPENCLAW_UNKNOWN_PROVIDER` | Unknown tool provider |
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
Apache-2.0
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @peac/adapter-openclaw - Background Emitter
|
|
3
|
+
*
|
|
4
|
+
* Background service for converting captured actions to signed PEAC receipts.
|
|
5
|
+
* Runs asynchronously to avoid blocking the sync capture path.
|
|
6
|
+
*/
|
|
7
|
+
import type { SpoolEntry } from '@peac/capture-core';
|
|
8
|
+
import type { ReceiptEmitter, EmitResult, OpenClawAdapterConfig } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Signer interface for receipt signing.
|
|
11
|
+
*
|
|
12
|
+
* Different implementations can support various key storage mechanisms:
|
|
13
|
+
* - Level 1: Environment variable (dev only)
|
|
14
|
+
* - Level 2: OS Keychain
|
|
15
|
+
* - Level 3: Sidecar process
|
|
16
|
+
* - Level 4: Hardware module (YubiKey, TPM, HSM)
|
|
17
|
+
*
|
|
18
|
+
* IMPORTANT: Implementations MUST include the key ID (kid) in the JWS header.
|
|
19
|
+
* The getKeyId() method allows callers to inspect which kid will be used
|
|
20
|
+
* without parsing the resulting JWS.
|
|
21
|
+
*/
|
|
22
|
+
export interface Signer {
|
|
23
|
+
/**
|
|
24
|
+
* Sign a payload and return JWS compact serialization.
|
|
25
|
+
* The JWS header MUST include the 'kid' claim for verifier key selection.
|
|
26
|
+
*/
|
|
27
|
+
sign(payload: unknown): Promise<string>;
|
|
28
|
+
/** Get the key ID (kid) that will be included in the JWS header */
|
|
29
|
+
getKeyId(): string;
|
|
30
|
+
/** Get the issuer URI */
|
|
31
|
+
getIssuer(): string;
|
|
32
|
+
/** Get the audience URI (optional) */
|
|
33
|
+
getAudience(): string | undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Receipt writer interface for persisting signed receipts.
|
|
37
|
+
*/
|
|
38
|
+
export interface ReceiptWriter {
|
|
39
|
+
/** Write a signed receipt */
|
|
40
|
+
write(receipt: SignedReceipt): Promise<string>;
|
|
41
|
+
/** Close the writer */
|
|
42
|
+
close(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Signed receipt ready for persistence.
|
|
46
|
+
*/
|
|
47
|
+
export interface SignedReceipt {
|
|
48
|
+
/** Receipt ID (rid) */
|
|
49
|
+
rid: string;
|
|
50
|
+
/** JWS compact serialization */
|
|
51
|
+
jws: string;
|
|
52
|
+
/** Interaction ID (for correlation) */
|
|
53
|
+
interaction_id: string;
|
|
54
|
+
/** Entry digest (for verification) */
|
|
55
|
+
entry_digest: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Configuration for creating a receipt emitter.
|
|
59
|
+
*/
|
|
60
|
+
export interface EmitterConfig {
|
|
61
|
+
/** Signer for receipt signing */
|
|
62
|
+
signer: Signer;
|
|
63
|
+
/** Writer for receipt persistence */
|
|
64
|
+
writer: ReceiptWriter;
|
|
65
|
+
/** Adapter configuration */
|
|
66
|
+
config?: OpenClawAdapterConfig;
|
|
67
|
+
/** Callback for emit events */
|
|
68
|
+
onEmit?: (result: EmitResult, entry: SpoolEntry) => void;
|
|
69
|
+
/** Callback for emit errors */
|
|
70
|
+
onError?: (error: Error, entry: SpoolEntry) => void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create a receipt emitter.
|
|
74
|
+
*
|
|
75
|
+
* @param emitterConfig - Configuration for the emitter
|
|
76
|
+
* @returns Receipt emitter instance
|
|
77
|
+
*/
|
|
78
|
+
export declare function createReceiptEmitter(emitterConfig: EmitterConfig): ReceiptEmitter;
|
|
79
|
+
/**
|
|
80
|
+
* Background emitter service that periodically drains a spool.
|
|
81
|
+
*/
|
|
82
|
+
export interface BackgroundEmitterService {
|
|
83
|
+
/** Start the background service */
|
|
84
|
+
start(): void;
|
|
85
|
+
/** Stop the background service */
|
|
86
|
+
stop(): void;
|
|
87
|
+
/** Trigger immediate drain */
|
|
88
|
+
drain(): Promise<void>;
|
|
89
|
+
/** Whether the service is running */
|
|
90
|
+
isRunning(): boolean;
|
|
91
|
+
/** Get emit statistics */
|
|
92
|
+
getStats(): EmitterStats;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Emitter statistics.
|
|
96
|
+
*/
|
|
97
|
+
export interface EmitterStats {
|
|
98
|
+
/** Total entries emitted */
|
|
99
|
+
emitted: number;
|
|
100
|
+
/** Total entries failed */
|
|
101
|
+
failed: number;
|
|
102
|
+
/** Last emit time */
|
|
103
|
+
lastEmitTime?: Date;
|
|
104
|
+
/** Last error */
|
|
105
|
+
lastError?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Configuration for background emitter service.
|
|
109
|
+
*/
|
|
110
|
+
export interface BackgroundServiceConfig {
|
|
111
|
+
/** Receipt emitter */
|
|
112
|
+
emitter: ReceiptEmitter;
|
|
113
|
+
/** Function to get pending spool entries */
|
|
114
|
+
getPendingEntries: () => Promise<SpoolEntry[]>;
|
|
115
|
+
/** Function to mark entry as emitted */
|
|
116
|
+
markEmitted: (entryDigest: string) => Promise<void>;
|
|
117
|
+
/** Drain interval in milliseconds (default: 1000) */
|
|
118
|
+
drainIntervalMs?: number;
|
|
119
|
+
/** Callback for service errors */
|
|
120
|
+
onError?: (error: Error) => void;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create a background emitter service.
|
|
124
|
+
*
|
|
125
|
+
* @param serviceConfig - Configuration for the service
|
|
126
|
+
* @returns Background emitter service instance
|
|
127
|
+
*/
|
|
128
|
+
export declare function createBackgroundService(serviceConfig: BackgroundServiceConfig): BackgroundEmitterService;
|
|
129
|
+
//# sourceMappingURL=emitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.d.ts","sourceRoot":"","sources":["../src/emitter.ts"],"names":[],"mappings":"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"}
|
package/dist/emitter.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @peac/adapter-openclaw - Background Emitter
|
|
4
|
+
*
|
|
5
|
+
* Background service for converting captured actions to signed PEAC receipts.
|
|
6
|
+
* Runs asynchronously to avoid blocking the sync capture path.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.createReceiptEmitter = createReceiptEmitter;
|
|
10
|
+
exports.createBackgroundService = createBackgroundService;
|
|
11
|
+
const capture_core_1 = require("@peac/capture-core");
|
|
12
|
+
const types_js_1 = require("./types.js");
|
|
13
|
+
/**
|
|
14
|
+
* Create a receipt emitter.
|
|
15
|
+
*
|
|
16
|
+
* @param emitterConfig - Configuration for the emitter
|
|
17
|
+
* @returns Receipt emitter instance
|
|
18
|
+
*/
|
|
19
|
+
function createReceiptEmitter(emitterConfig) {
|
|
20
|
+
const { signer, writer, onEmit, onError } = emitterConfig;
|
|
21
|
+
let closed = false;
|
|
22
|
+
return {
|
|
23
|
+
async emit(entry) {
|
|
24
|
+
if (closed) {
|
|
25
|
+
return {
|
|
26
|
+
success: false,
|
|
27
|
+
error_code: 'E_EMITTER_CLOSED',
|
|
28
|
+
error_message: 'Emitter has been closed',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
// Convert SpoolEntry to InteractionEvidence
|
|
33
|
+
// Note: Platform info is already in the entry.action from the mapper
|
|
34
|
+
const interaction = (0, capture_core_1.toInteractionEvidence)(entry);
|
|
35
|
+
// Build the receipt payload
|
|
36
|
+
const receiptPayload = buildReceiptPayload(interaction, entry, signer);
|
|
37
|
+
// Sign the receipt
|
|
38
|
+
const jws = await signer.sign(receiptPayload);
|
|
39
|
+
// Build signed receipt
|
|
40
|
+
const signedReceipt = {
|
|
41
|
+
rid: receiptPayload.rid,
|
|
42
|
+
jws,
|
|
43
|
+
interaction_id: entry.action.id,
|
|
44
|
+
entry_digest: entry.entry_digest,
|
|
45
|
+
};
|
|
46
|
+
// Write the receipt
|
|
47
|
+
const receiptPath = await writer.write(signedReceipt);
|
|
48
|
+
const result = {
|
|
49
|
+
success: true,
|
|
50
|
+
receipt_path: receiptPath,
|
|
51
|
+
receipt_id: receiptPayload.rid,
|
|
52
|
+
};
|
|
53
|
+
if (onEmit) {
|
|
54
|
+
onEmit(result, entry);
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
60
|
+
if (onError) {
|
|
61
|
+
onError(error instanceof Error ? error : new Error(errorMessage), entry);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error_code: types_js_1.OPENCLAW_ERROR_CODES.SIGNING_FAILED,
|
|
66
|
+
error_message: `Failed to emit receipt: ${errorMessage}`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
async flush() {
|
|
71
|
+
// No-op: entries are emitted immediately via emit()
|
|
72
|
+
// This method exists for API consistency
|
|
73
|
+
},
|
|
74
|
+
async close() {
|
|
75
|
+
closed = true;
|
|
76
|
+
await writer.close();
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Build the receipt payload from interaction evidence.
|
|
82
|
+
*/
|
|
83
|
+
function buildReceiptPayload(interaction, entry, signer) {
|
|
84
|
+
const now = Math.floor(Date.now() / 1000);
|
|
85
|
+
const rid = generateReceiptId(entry.entry_digest);
|
|
86
|
+
const payload = {
|
|
87
|
+
iss: signer.getIssuer(),
|
|
88
|
+
iat: now,
|
|
89
|
+
rid,
|
|
90
|
+
evidence: {
|
|
91
|
+
extensions: {
|
|
92
|
+
'org.peacprotocol/interaction@0.1': interaction,
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
const audience = signer.getAudience();
|
|
97
|
+
if (audience) {
|
|
98
|
+
payload.aud = audience;
|
|
99
|
+
}
|
|
100
|
+
return payload;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Generate a deterministic receipt ID from entry digest.
|
|
104
|
+
*
|
|
105
|
+
* Using a deterministic ID (derived from entry_digest) provides:
|
|
106
|
+
* - Idempotency: same entry always produces same rid
|
|
107
|
+
* - Replay safety: retries don't create duplicates
|
|
108
|
+
* - Correlation: rid can be traced back to spool entry
|
|
109
|
+
*
|
|
110
|
+
* Format: r_{first 32 chars of entry_digest}
|
|
111
|
+
*/
|
|
112
|
+
function generateReceiptId(entryDigest) {
|
|
113
|
+
// Use first 32 chars of entry digest for reasonable uniqueness
|
|
114
|
+
// while keeping the ID short enough for practical use
|
|
115
|
+
return `r_${entryDigest.slice(0, 32)}`;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Create a background emitter service.
|
|
119
|
+
*
|
|
120
|
+
* @param serviceConfig - Configuration for the service
|
|
121
|
+
* @returns Background emitter service instance
|
|
122
|
+
*/
|
|
123
|
+
function createBackgroundService(serviceConfig) {
|
|
124
|
+
const { emitter, getPendingEntries, markEmitted, drainIntervalMs = 1000, onError, } = serviceConfig;
|
|
125
|
+
let running = false;
|
|
126
|
+
let stopping = false;
|
|
127
|
+
let inFlight = false;
|
|
128
|
+
let intervalHandle;
|
|
129
|
+
const stats = {
|
|
130
|
+
emitted: 0,
|
|
131
|
+
failed: 0,
|
|
132
|
+
};
|
|
133
|
+
const drainOnce = async () => {
|
|
134
|
+
// Prevent overlapping drains - if a drain takes longer than the
|
|
135
|
+
// interval, skip this tick rather than double-processing
|
|
136
|
+
if (inFlight)
|
|
137
|
+
return;
|
|
138
|
+
inFlight = true;
|
|
139
|
+
try {
|
|
140
|
+
const entries = await getPendingEntries();
|
|
141
|
+
for (const entry of entries) {
|
|
142
|
+
// Check if service is being stopped during processing
|
|
143
|
+
if (stopping)
|
|
144
|
+
break;
|
|
145
|
+
const result = await emitter.emit(entry);
|
|
146
|
+
if (result.success) {
|
|
147
|
+
await markEmitted(entry.entry_digest);
|
|
148
|
+
stats.emitted++;
|
|
149
|
+
stats.lastEmitTime = new Date();
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
stats.failed++;
|
|
153
|
+
stats.lastError = result.error_message;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
stats.lastError = error instanceof Error ? error.message : String(error);
|
|
159
|
+
if (onError) {
|
|
160
|
+
onError(error instanceof Error ? error : new Error(String(error)));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
inFlight = false;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
start() {
|
|
169
|
+
if (running)
|
|
170
|
+
return;
|
|
171
|
+
running = true;
|
|
172
|
+
intervalHandle = setInterval(drainOnce, drainIntervalMs);
|
|
173
|
+
// Run immediately on start
|
|
174
|
+
drainOnce();
|
|
175
|
+
},
|
|
176
|
+
stop() {
|
|
177
|
+
if (!running)
|
|
178
|
+
return;
|
|
179
|
+
stopping = true;
|
|
180
|
+
running = false;
|
|
181
|
+
if (intervalHandle) {
|
|
182
|
+
clearInterval(intervalHandle);
|
|
183
|
+
intervalHandle = undefined;
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
async drain() {
|
|
187
|
+
await drainOnce();
|
|
188
|
+
},
|
|
189
|
+
isRunning() {
|
|
190
|
+
return running;
|
|
191
|
+
},
|
|
192
|
+
getStats() {
|
|
193
|
+
return { ...stats };
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=emitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.js","sourceRoot":"","sources":["../src/emitter.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @peac/adapter-openclaw - Hook Bindings
|
|
3
|
+
*
|
|
4
|
+
* Hook bindings for OpenClaw tool call capture.
|
|
5
|
+
* Designed for sync capture (< 10ms target).
|
|
6
|
+
*/
|
|
7
|
+
import type { CaptureSession, SpoolEntry } from '@peac/capture-core';
|
|
8
|
+
import type { OpenClawToolCallEvent, OpenClawAdapterConfig, MappingResult } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Result of a hook capture operation.
|
|
11
|
+
* More flexible than CaptureResult to allow adapter-specific error codes.
|
|
12
|
+
*/
|
|
13
|
+
export type HookCaptureResult = {
|
|
14
|
+
success: true;
|
|
15
|
+
entry: SpoolEntry;
|
|
16
|
+
} | {
|
|
17
|
+
success: false;
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Hook handler for OpenClaw tool call events.
|
|
23
|
+
*/
|
|
24
|
+
export interface OpenClawHookHandler {
|
|
25
|
+
/** Handle after_tool_call hook */
|
|
26
|
+
afterToolCall(event: OpenClawToolCallEvent): Promise<HookCaptureResult>;
|
|
27
|
+
/** Get the underlying capture session */
|
|
28
|
+
getSession(): CaptureSession;
|
|
29
|
+
/** Close the handler */
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Configuration for creating a hook handler.
|
|
34
|
+
*/
|
|
35
|
+
export interface HookHandlerConfig {
|
|
36
|
+
/** Capture session to use */
|
|
37
|
+
session: CaptureSession;
|
|
38
|
+
/** Adapter configuration */
|
|
39
|
+
config?: OpenClawAdapterConfig;
|
|
40
|
+
/** Callback for capture events (for telemetry/logging) */
|
|
41
|
+
onCapture?: (result: HookCaptureResult, event: OpenClawToolCallEvent) => void;
|
|
42
|
+
/** Callback for mapping errors */
|
|
43
|
+
onMappingError?: (result: MappingResult, event: OpenClawToolCallEvent) => void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Create a hook handler for OpenClaw tool call events.
|
|
47
|
+
*
|
|
48
|
+
* @param handlerConfig - Configuration for the handler
|
|
49
|
+
* @returns Hook handler instance
|
|
50
|
+
*/
|
|
51
|
+
export declare function createHookHandler(handlerConfig: HookHandlerConfig): OpenClawHookHandler;
|
|
52
|
+
/**
|
|
53
|
+
* Capture multiple tool call events in sequence.
|
|
54
|
+
*
|
|
55
|
+
* Note: Events are captured in order. For parallel capture, use individual
|
|
56
|
+
* afterToolCall calls with Promise.all.
|
|
57
|
+
*
|
|
58
|
+
* @param handler - Hook handler
|
|
59
|
+
* @param events - Array of tool call events
|
|
60
|
+
* @returns Array of capture results (same order as events)
|
|
61
|
+
*/
|
|
62
|
+
export declare function captureBatch(handler: OpenClawHookHandler, events: OpenClawToolCallEvent[]): Promise<HookCaptureResult[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Capture multiple tool call events in parallel.
|
|
65
|
+
*
|
|
66
|
+
* Warning: Parallel capture may result in non-deterministic chain ordering.
|
|
67
|
+
* Use captureBatch for deterministic ordering.
|
|
68
|
+
*
|
|
69
|
+
* @param handler - Hook handler
|
|
70
|
+
* @param events - Array of tool call events
|
|
71
|
+
* @returns Array of capture results (same order as events)
|
|
72
|
+
*/
|
|
73
|
+
export declare function captureParallel(handler: OpenClawHookHandler, events: OpenClawToolCallEvent[]): Promise<HookCaptureResult[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Session history tailer for fallback capture.
|
|
76
|
+
*
|
|
77
|
+
* If OpenClaw hooks don't provide complete event data, this can poll
|
|
78
|
+
* the session history API to backfill missed events.
|
|
79
|
+
*/
|
|
80
|
+
export interface SessionHistoryTailer {
|
|
81
|
+
/** Start tailing session history */
|
|
82
|
+
start(): void;
|
|
83
|
+
/** Stop tailing */
|
|
84
|
+
stop(): void;
|
|
85
|
+
/** Get the last processed event ID */
|
|
86
|
+
getLastEventId(): string | undefined;
|
|
87
|
+
/** Whether the tailer is running */
|
|
88
|
+
isRunning(): boolean;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Configuration for session history tailer.
|
|
92
|
+
*/
|
|
93
|
+
export interface TailerConfig {
|
|
94
|
+
/** Hook handler to use for capture */
|
|
95
|
+
handler: OpenClawHookHandler;
|
|
96
|
+
/** Session ID to tail */
|
|
97
|
+
sessionId: string;
|
|
98
|
+
/** Polling interval in milliseconds (default: 1000) */
|
|
99
|
+
pollIntervalMs?: number;
|
|
100
|
+
/** Function to fetch session history */
|
|
101
|
+
fetchHistory: (sessionId: string, afterEventId?: string) => Promise<OpenClawToolCallEvent[]>;
|
|
102
|
+
/** Callback for tailer errors */
|
|
103
|
+
onError?: (error: Error) => void;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Create a session history tailer.
|
|
107
|
+
*
|
|
108
|
+
* @param tailerConfig - Configuration for the tailer
|
|
109
|
+
* @returns Session history tailer instance
|
|
110
|
+
*/
|
|
111
|
+
export declare function createSessionHistoryTailer(tailerConfig: TailerConfig): SessionHistoryTailer;
|
|
112
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAiB,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAO9F;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAMtD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,kCAAkC;IAClC,aAAa,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAExE,yCAAyC;IACzC,UAAU,IAAI,cAAc,CAAC;IAE7B,wBAAwB;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,OAAO,EAAE,cAAc,CAAC;IAExB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAE/B,0DAA0D;IAC1D,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAE9E,kCAAkC;IAClC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAChF;AAMD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,iBAAiB,GAAG,mBAAmB,CA6CvF;AAMD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,qBAAqB,EAAE,GAC9B,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAS9B;AAED;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,qBAAqB,EAAE,GAC9B,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAE9B;AAMD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,oCAAoC;IACpC,KAAK,IAAI,IAAI,CAAC;IAEd,mBAAmB;IACnB,IAAI,IAAI,IAAI,CAAC;IAEb,sCAAsC;IACtC,cAAc,IAAI,MAAM,GAAG,SAAS,CAAC;IAErC,oCAAoC;IACpC,SAAS,IAAI,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,OAAO,EAAE,mBAAmB,CAAC;IAE7B,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAElB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,wCAAwC;IACxC,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAE7F,iCAAiC;IACjC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,EAAE,YAAY,GAAG,oBAAoB,CA2D3F"}
|