@troykelly/openclaw-projects 0.0.1 → 0.0.3

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 CHANGED
@@ -1,376 +1,321 @@
1
1
  # @troykelly/openclaw-projects
2
2
 
3
- An [OpenClaw](https://docs.openclaw.ai/) plugin that connects agents to the openclaw-projects backend for project management, memory, todos, and contacts.
3
+ An [OpenClaw](https://docs.openclaw.ai/) plugin that connects agents to the openclaw-projects backend for project management, memory, todos, contacts, and communications.
4
4
 
5
5
  > **Note:** This is a third-party plugin — not part of OpenClaw itself. It provides OpenClaw agents with tools to interact with the [openclaw-projects](https://github.com/troykelly/openclaw-projects) backend service.
6
6
 
7
7
  ## Features
8
8
 
9
- - **Memory Management**: Store, recall, and forget memories with semantic search
9
+ - **Memory Management**: Store, recall, and forget memories with semantic search (pgvector)
10
10
  - **Project Management**: List, get, and create projects
11
11
  - **Todo Management**: Manage todos with completion tracking
12
- - **Contact Management**: Search, get, and create contacts
12
+ - **Contact Management**: Search, get, and create contacts with relationship mapping
13
+ - **Communications**: Send SMS (Twilio) and email (Postmark) directly from agents
14
+ - **Message History**: Search and browse message threads across channels
15
+ - **Skill Store**: Persist and query structured data for agent skills
13
16
  - **Auto-Recall**: Automatically inject relevant context into conversations
14
17
  - **Auto-Capture**: Capture important information from completed conversations
15
- - **CLI Commands**: Debug and manage the plugin from the command line
16
- - **Multi-User Support**: Flexible user scoping (agent, session, identity)
18
+ - **Bundled Skills**: 4 ready-to-use skills for common workflows
17
19
 
18
20
  ## Installation
19
21
 
22
+ ### Via OpenClaw CLI (recommended)
23
+
20
24
  ```bash
21
- pnpm add @troykelly/openclaw-projects
25
+ openclaw plugins install @troykelly/openclaw-projects
22
26
  ```
23
27
 
24
- ## Quick Start
28
+ Then configure the plugin in your OpenClaw config file (`~/.openclaw/config.yaml` or equivalent):
25
29
 
26
- ```typescript
27
- import { register } from '@troykelly/openclaw-projects'
30
+ ```yaml
31
+ plugins:
32
+ entries:
33
+ openclaw-projects:
34
+ enabled: true
35
+ config:
36
+ apiUrl: https://your-backend.example.com
37
+ apiKey: your-api-key
38
+ ```
28
39
 
29
- const plugin = register({
30
- config: {
31
- apiUrl: 'https://your-backend.example.com',
32
- apiKey: process.env.OPENCLAW_API_KEY,
33
- },
34
- })
40
+ ### Via npm (for programmatic use)
35
41
 
36
- // Use tools
37
- const result = await plugin.tools.memoryRecall.execute({
38
- query: 'user preferences',
39
- })
42
+ ```bash
43
+ pnpm add @troykelly/openclaw-projects
40
44
  ```
41
45
 
42
- ## Configuration
46
+ This method is for integrating the plugin programmatically outside of the OpenClaw runtime. Most users should use the OpenClaw CLI method above.
43
47
 
44
- | Option | Type | Default | Description |
45
- |--------|------|---------|-------------|
46
- | `apiUrl` | string | **required** | Backend API URL |
47
- | `apiKey` | string | **required** | API authentication key |
48
- | `autoRecall` | boolean | `true` | Enable auto-recall hook |
49
- | `autoCapture` | boolean | `true` | Enable auto-capture hook |
50
- | `userScoping` | string | `'agent'` | User scoping mode |
51
- | `maxRecallMemories` | number | `5` | Max memories to return |
52
- | `minRecallScore` | number | `0.7` | Minimum similarity score |
53
- | `timeout` | number | `30000` | API timeout (ms) |
54
- | `maxRetries` | number | `3` | Max retry attempts |
55
- | `debug` | boolean | `false` | Enable debug logging |
48
+ ## Verification
56
49
 
57
- ### User Scoping Modes
50
+ After installation, verify the plugin is loaded:
58
51
 
59
- | Mode | Description | Use Case |
60
- |------|-------------|----------|
61
- | `agent` | Scope by agent ID | Single user per agent |
62
- | `session` | Scope by session key | Maximum isolation |
63
- | `identity` | Scope by canonical identity | Shared identity across agents |
52
+ ```bash
53
+ openclaw plugins info openclaw-projects
54
+ ```
64
55
 
65
- ### Environment Variables
56
+ Check that the plugin is healthy and can reach the backend:
66
57
 
67
58
  ```bash
68
- OPENCLAW_API_URL=https://your-backend.example.com
69
- OPENCLAW_API_KEY=your-api-key
59
+ openclaw plugins doctor
70
60
  ```
71
61
 
72
- ## Tools
73
-
74
- ### Memory Tools
62
+ ## Configuration
75
63
 
76
- #### `memory_recall`
77
- Search memories semantically.
64
+ Configure the plugin in your OpenClaw config file or pass config programmatically.
78
65
 
79
- ```typescript
80
- const result = await plugin.tools.memoryRecall.execute({
81
- query: 'user preferences for notifications',
82
- limit: 10, // optional, default: 5
83
- category: 'preference', // optional filter
84
- })
85
- ```
66
+ ### Required Settings
86
67
 
87
- #### `memory_store`
88
- Save information to long-term memory.
68
+ | Option | Type | Description |
69
+ |--------|------|-------------|
70
+ | `apiUrl` | string | Backend API URL (must be HTTPS in production) |
71
+ | `apiKey` | string | API authentication key (direct value) |
89
72
 
90
- ```typescript
91
- const result = await plugin.tools.memoryStore.execute({
92
- text: 'User prefers dark mode',
93
- category: 'preference', // preference, fact, decision, context, other
94
- importance: 0.8, // optional, 0-1
95
- })
96
- ```
73
+ You must provide the API key via one of three methods:
97
74
 
98
- #### `memory_forget`
99
- Delete memories (GDPR data portability).
75
+ | Method | Config Key | Description |
76
+ |--------|-----------|-------------|
77
+ | Direct value | `apiKey` | Plaintext key (for development only) |
78
+ | File reference | `apiKeyFile` | Path to file containing key (e.g., `~/.secrets/api_key`) |
79
+ | Command | `apiKeyCommand` | Shell command to retrieve key (e.g., `op read op://Personal/openclaw/api_key`) |
100
80
 
101
- ```typescript
102
- // By ID
103
- const result = await plugin.tools.memoryForget.execute({
104
- memoryId: '123e4567-e89b-12d3-a456-426614174000',
105
- })
81
+ ### Optional Settings
106
82
 
107
- // By query (bulk delete)
108
- const result = await plugin.tools.memoryForget.execute({
109
- query: 'outdated preferences',
110
- confirm: true, // required for bulk delete
111
- })
83
+ | Option | Type | Default | Description |
84
+ |--------|------|---------|-------------|
85
+ | `autoRecall` | boolean | `true` | Inject relevant memories at conversation start |
86
+ | `autoCapture` | boolean | `true` | Capture important info from completed conversations |
87
+ | `userScoping` | string | `'agent'` | User scoping mode (`agent`, `session`, `identity`) |
88
+ | `maxRecallMemories` | number | `5` | Max memories to inject in auto-recall |
89
+ | `minRecallScore` | number | `0.7` | Minimum similarity score for auto-recall (0-1) |
90
+ | `timeout` | number | `30000` | API request timeout (ms) |
91
+ | `maxRetries` | number | `3` | Max retry attempts for failed requests |
92
+ | `debug` | boolean | `false` | Enable debug logging (never logs secrets) |
93
+
94
+ ### Secret Management
95
+
96
+ All secret fields (API key, Twilio credentials, Postmark token) support three resolution methods. The plugin resolves secrets in priority order: command > file > direct value.
97
+
98
+ ```yaml
99
+ plugins:
100
+ entries:
101
+ openclaw-projects:
102
+ enabled: true
103
+ config:
104
+ apiUrl: https://your-backend.example.com
105
+ # Option 1: Direct value (development only)
106
+ apiKey: sk-dev-key-here
107
+ # Option 2: File reference
108
+ # apiKeyFile: ~/.secrets/openclaw-api-key
109
+ # Option 3: Command (e.g., 1Password CLI)
110
+ # apiKeyCommand: op read op://Personal/openclaw/api_key
112
111
  ```
113
112
 
114
- ### Project Tools
113
+ ### Twilio SMS (optional)
115
114
 
116
- #### `project_list`
117
- List projects with optional filtering.
115
+ To enable SMS sending, add Twilio credentials using the same direct/file/command pattern:
118
116
 
119
- ```typescript
120
- const result = await plugin.tools.projectList.execute({
121
- status: 'active', // optional: active, completed, archived, on_hold
122
- limit: 20, // optional
123
- })
117
+ ```yaml
118
+ twilioAccountSid: AC...
119
+ twilioAuthToken: your-auth-token
120
+ twilioPhoneNumber: "+15551234567"
124
121
  ```
125
122
 
126
- #### `project_get`
127
- Get a specific project by ID.
123
+ ### Postmark Email (optional)
124
+
125
+ To enable email sending, add Postmark credentials:
128
126
 
129
- ```typescript
130
- const result = await plugin.tools.projectGet.execute({
131
- id: '123e4567-e89b-12d3-a456-426614174000',
132
- })
127
+ ```yaml
128
+ postmarkToken: your-postmark-token
129
+ postmarkFromEmail: noreply@example.com
133
130
  ```
134
131
 
135
- #### `project_create`
136
- Create a new project.
132
+ ### User Scoping Modes
137
133
 
138
- ```typescript
139
- const result = await plugin.tools.projectCreate.execute({
140
- name: 'Home Renovation',
141
- description: 'Kitchen remodel project', // optional
142
- status: 'active', // optional
143
- })
144
- ```
134
+ | Mode | Description | Use Case |
135
+ |------|-------------|----------|
136
+ | `agent` | Scope by agent ID | Single user per agent (default) |
137
+ | `session` | Scope by session key | Maximum isolation between sessions |
138
+ | `identity` | Scope by canonical identity | Shared identity across agents |
145
139
 
146
- ### Todo Tools
140
+ ## Tools
147
141
 
148
- #### `todo_list`
149
- List todos with optional filtering.
142
+ The plugin registers 27 tools that agents can use. Tools are automatically available to any agent with the plugin enabled.
150
143
 
151
- ```typescript
152
- const result = await plugin.tools.todoList.execute({
153
- projectId: '123e4567-e89b-12d3-a456-426614174000', // optional
154
- completed: false, // optional
155
- limit: 50, // optional
156
- })
157
- ```
144
+ ### Memory Tools
158
145
 
159
- #### `todo_create`
160
- Create a new todo.
146
+ | Tool | Description |
147
+ |------|-------------|
148
+ | `memory_recall` | Search memories semantically by query |
149
+ | `memory_store` | Store a new memory (preference, fact, decision, context) |
150
+ | `memory_forget` | Delete memories by ID or search query |
161
151
 
162
- ```typescript
163
- const result = await plugin.tools.todoCreate.execute({
164
- title: 'Buy groceries',
165
- projectId: '123e4567-e89b-12d3-a456-426614174000', // optional
166
- dueDate: '2024-01-15', // optional, ISO 8601
167
- })
168
- ```
152
+ ### Project Tools
169
153
 
170
- #### `todo_complete`
171
- Mark a todo as complete.
154
+ | Tool | Description |
155
+ |------|-------------|
156
+ | `project_list` | List projects with optional status filter |
157
+ | `project_get` | Get full details of a specific project |
158
+ | `project_create` | Create a new project |
172
159
 
173
- ```typescript
174
- const result = await plugin.tools.todoComplete.execute({
175
- id: '123e4567-e89b-12d3-a456-426614174000',
176
- })
177
- ```
160
+ ### Todo Tools
161
+
162
+ | Tool | Description |
163
+ |------|-------------|
164
+ | `todo_list` | List todos, optionally filtered by project or status |
165
+ | `todo_create` | Create a new todo item |
166
+ | `todo_complete` | Mark a todo as complete |
178
167
 
179
168
  ### Contact Tools
180
169
 
181
- #### `contact_search`
182
- Search contacts.
170
+ | Tool | Description |
171
+ |------|-------------|
172
+ | `contact_search` | Search contacts by name, email, or other fields |
173
+ | `contact_get` | Get full details of a specific contact |
174
+ | `contact_create` | Create a new contact |
183
175
 
184
- ```typescript
185
- const result = await plugin.tools.contactSearch.execute({
186
- query: 'Alice',
187
- limit: 10, // optional
188
- })
189
- ```
176
+ ### Communication Tools
190
177
 
191
- #### `contact_get`
192
- Get a specific contact by ID.
178
+ | Tool | Description |
179
+ |------|-------------|
180
+ | `sms_send` | Send an SMS message (requires Twilio config) |
181
+ | `email_send` | Send an email message (requires Postmark config) |
182
+ | `message_search` | Search message history semantically |
183
+ | `thread_list` | List message threads (conversations) |
184
+ | `thread_get` | Get a thread with full message history |
193
185
 
194
- ```typescript
195
- const result = await plugin.tools.contactGet.execute({
196
- id: '123e4567-e89b-12d3-a456-426614174000',
197
- })
198
- ```
186
+ ### Relationship Tools
199
187
 
200
- #### `contact_create`
201
- Create a new contact.
188
+ | Tool | Description |
189
+ |------|-------------|
190
+ | `relationship_set` | Record a relationship between contacts |
191
+ | `relationship_query` | Query a contact's relationships |
202
192
 
203
- ```typescript
204
- const result = await plugin.tools.contactCreate.execute({
205
- name: 'Alice Smith',
206
- email: 'alice@example.com', // optional
207
- phone: '+1-555-123-4567', // optional
208
- })
209
- ```
193
+ ### Skill Store Tools
210
194
 
211
- ## Lifecycle Hooks
195
+ | Tool | Description |
196
+ |------|-------------|
197
+ | `skill_store_put` | Store or update data in the skill store |
198
+ | `skill_store_get` | Retrieve an item by ID or composite key |
199
+ | `skill_store_list` | List items with filtering and pagination |
200
+ | `skill_store_delete` | Delete an item (soft delete) |
201
+ | `skill_store_search` | Search items by text or semantic similarity |
202
+ | `skill_store_collections` | List all collections with item counts |
203
+ | `skill_store_aggregate` | Run aggregations on skill store items |
212
204
 
213
- ### `beforeAgentStart` (Auto-Recall)
205
+ ### Other Tools
214
206
 
215
- Automatically fetches relevant context before the agent processes a prompt.
207
+ | Tool | Description |
208
+ |------|-------------|
209
+ | `file_share` | Generate a time-limited shareable download link |
216
210
 
217
- ```typescript
218
- const context = await plugin.hooks.beforeAgentStart({
219
- prompt: 'What are my notification preferences?',
220
- })
211
+ ## Skills
221
212
 
222
- if (context) {
223
- // Prepend context.prependContext to the conversation
224
- }
225
- ```
213
+ The plugin includes 4 bundled skills that agents can invoke as high-level workflows. Skills combine multiple tools to accomplish common tasks.
226
214
 
227
- ### `agentEnd` (Auto-Capture)
215
+ ### `contact-lookup`
228
216
 
229
- Automatically captures important information after a conversation ends.
217
+ Look up contact information and recent communications.
230
218
 
231
- ```typescript
232
- await plugin.hooks.agentEnd({
233
- messages: [
234
- { role: 'user', content: 'Remember I prefer email notifications' },
235
- { role: 'assistant', content: 'Noted! I will remember your preference.' },
236
- ],
237
- })
219
+ ```
220
+ /contact-lookup name="Alice Smith"
238
221
  ```
239
222
 
240
- ## CLI Commands
223
+ Searches contacts, retrieves details, shows recent messages, related projects/tasks, and stored memories about the person.
241
224
 
242
- The plugin provides CLI command handlers that can be registered with OpenClaw:
225
+ ### `daily-summary`
243
226
 
244
- ### `status`
245
- Check API connectivity.
227
+ Get a summary of today's tasks, messages, and activities.
246
228
 
247
- ```typescript
248
- const result = await plugin.cli.status()
249
- // { success: true, message: 'API is healthy (latency: 50ms)', data: { ... } }
229
+ ```
230
+ /daily-summary
250
231
  ```
251
232
 
252
- ### `users`
253
- Show user scoping configuration.
233
+ Shows tasks due today, recent messages, upcoming deadlines, and items requiring attention.
254
234
 
255
- ```typescript
256
- const result = await plugin.cli.users()
257
- // { success: true, data: { scopingMode: 'agent', description: '...', currentUserId: '...' } }
258
- ```
235
+ ### `project-status`
259
236
 
260
- ### `recall`
261
- Search memories from CLI.
237
+ Get a status overview of a specific project.
262
238
 
263
- ```typescript
264
- const result = await plugin.cli.recall({ query: 'preferences', limit: 10 })
265
- // { success: true, data: { memories: [...], query: '...', limit: 10 } }
239
+ ```
240
+ /project-status project="Home Renovation"
266
241
  ```
267
242
 
268
- ### `stats`
269
- Show memory statistics.
243
+ Shows project overview, task breakdown with completion percentage, recent activity, blockers, and recommended next steps.
270
244
 
271
- ```typescript
272
- const result = await plugin.cli.stats()
273
- // { success: true, data: { totalMemories: 42, byCategory: { ... } } }
274
- ```
245
+ ### `send-reminder`
275
246
 
276
- ### `export`
277
- Export all memories (GDPR data portability).
247
+ Send a reminder message to a contact via SMS or email.
278
248
 
279
- ```typescript
280
- const result = await plugin.cli.export({ output: '/path/to/export.json' })
281
- // { success: true, data: { memories: [...], exportedAt: '...', userId: '...' } }
249
+ ```
250
+ /send-reminder contact="Alice" message="Don't forget the meeting tomorrow" channel="sms"
282
251
  ```
283
252
 
284
- ## Health Check
253
+ Looks up the contact, verifies their endpoint, sends the message, and confirms delivery.
285
254
 
286
- ```typescript
287
- const health = await plugin.healthCheck()
288
- if (!health.healthy) {
289
- console.error('Plugin unhealthy:', health.error)
290
- }
291
- ```
255
+ ## Lifecycle Hooks
256
+
257
+ ### `before_agent_start` (Auto-Recall)
258
+
259
+ When `autoRecall` is enabled (default), the plugin automatically searches for relevant memories before each conversation. It uses the user's prompt for semantic search and injects matching memories as context via `prependContext`.
260
+
261
+ ### `agent_end` (Auto-Capture)
262
+
263
+ When `autoCapture` is enabled (default), the plugin automatically analyzes completed conversations and stores important information (preferences, facts, decisions) as memories for future recall.
292
264
 
293
265
  ## Security
294
266
 
295
- ### API Key Management
267
+ ### Secret Management
296
268
 
297
- - Store API keys in environment variables, never in code
298
- - Use secrets management in production (Vault, AWS Secrets Manager, etc.)
299
- - Rotate keys regularly
269
+ - Use file references or command execution for secrets in production
270
+ - Direct values are for development only
271
+ - The plugin supports 1Password CLI, Vault, AWS Secrets Manager, or any command-line tool
272
+ - Secret files are checked for world-readable permissions (warns if `chmod 644`)
300
273
 
301
274
  ### Data Isolation
302
275
 
303
276
  - All data is scoped to the configured user scope
304
277
  - Cross-user access is prevented at the API level
305
- - Audit logs track all data access
278
+
279
+ ### HTTPS
280
+
281
+ - HTTPS is required in production (`NODE_ENV=production`)
282
+ - HTTP is permitted for local development only
306
283
 
307
284
  ### Sensitive Content
308
285
 
309
- - The plugin filters sensitive content (API keys, passwords, credit cards)
310
- - PII is not logged at info level
286
+ - Secrets are never logged (config is redacted in logs)
311
287
  - Error messages are sanitized to prevent information leakage
312
288
 
313
- ### HTTPS
314
-
315
- - Use HTTPS in production
316
- - HTTP is only recommended for local development
289
+ ## Troubleshooting
317
290
 
318
- ## Error Handling
291
+ ### Plugin not loading
319
292
 
320
- All tool executions return a result object:
293
+ Verify the plugin is installed and the manifest is detected:
321
294
 
322
- ```typescript
323
- interface ToolResult {
324
- success: boolean
325
- content?: string // Human-readable response
326
- data?: unknown // Structured data
327
- error?: string // Error message if success is false
328
- }
295
+ ```bash
296
+ openclaw plugins info openclaw-projects
329
297
  ```
330
298
 
331
- ## Troubleshooting
332
-
333
- ### Connection Issues
299
+ ### Connection issues
334
300
 
335
- ```typescript
336
- // Check health
337
- const health = await plugin.healthCheck()
338
- console.log('Healthy:', health.healthy, 'Error:', health.error)
301
+ Check that the backend API is reachable:
339
302
 
340
- // Check status via CLI
341
- const status = await plugin.cli.status()
342
- console.log('Status:', status.message, 'Latency:', status.data?.latencyMs)
303
+ ```bash
304
+ openclaw plugins doctor
343
305
  ```
344
306
 
345
- ### No Memories Found
307
+ ### No memories found
346
308
 
347
309
  - Verify the user scoping mode matches your setup
348
310
  - Check that memories were stored for the same user scope
349
311
  - Try broadening your search query
350
312
 
351
- ### API Errors
313
+ ### API errors
352
314
 
353
- - Verify API URL is correct and accessible
354
- - Check API key is valid
315
+ - Verify `apiUrl` is correct and accessible
316
+ - Check that the API key is valid
355
317
  - Review network connectivity
356
318
 
357
- ## API Reference
358
-
359
- Full TypeScript types are exported:
360
-
361
- ```typescript
362
- import type {
363
- PluginConfig,
364
- PluginInstance,
365
- MemoryRecallParams,
366
- MemoryStoreParams,
367
- ProjectListParams,
368
- TodoCreateParams,
369
- ContactSearchParams,
370
- // ... and more
371
- } from '@troykelly/openclaw-projects'
372
- ```
373
-
374
319
  ## Contributing
375
320
 
376
321
  1. Fork the repository
@@ -385,5 +330,6 @@ MIT
385
330
  ## Links
386
331
 
387
332
  - [OpenClaw Documentation](https://docs.openclaw.ai/)
333
+ - [OpenClaw Plugin Guide](https://docs.openclaw.ai/plugins)
388
334
  - [openclaw-projects Backend](https://github.com/troykelly/openclaw-projects)
389
335
  - [Report Issues](https://github.com/troykelly/openclaw-projects/issues)
package/dist/config.d.ts CHANGED
@@ -321,4 +321,16 @@ export declare function redactConfig(config: PluginConfig): PluginConfig;
321
321
  * @throws If required secrets cannot be resolved
322
322
  */
323
323
  export declare function resolveConfigSecrets(rawConfig: RawPluginConfig): Promise<PluginConfig>;
324
+ /**
325
+ * Resolves all secrets synchronously to produce a resolved config.
326
+ *
327
+ * Used during plugin registration where blocking I/O is acceptable.
328
+ * OpenClaw's loader does not await the register function, so all
329
+ * config resolution must complete synchronously.
330
+ *
331
+ * @param rawConfig - The raw plugin configuration with secret references
332
+ * @returns The resolved plugin configuration with actual secret values
333
+ * @throws If required secrets cannot be resolved
334
+ */
335
+ export declare function resolveConfigSecretsSync(rawConfig: RawPluginConfig): PluginConfig;
324
336
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,6CAA2C,CAAA;AACzE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAS3D;;;GAGG;AACH,eAAO,MAAM,qBAAqB;IAE9B,oDAAoD;;IAUpD,4CAA4C;;IAE5C,sCAAsC;;IAEtC,wCAAwC;;IAIxC,wCAAwC;;IAExC,iDAAiD;;IAEjD,wCAAwC;;IAIxC,uCAAuC;;IAEvC,gDAAgD;;IAEhD,uCAAuC;;IAIvC,yCAAyC;;IAEzC,kDAAkD;;IAElD,yCAAyC;;IAIzC,wCAAwC;;IAExC,6CAA6C;;IAE7C,oCAAoC;;IAIpC,iDAAiD;;IAEjD,kDAAkD;;IAElD,yCAAyC;;IAGzC,2DAA2D;;IAS3D,mEAAmE;;IAGnE,8DAA8D;;IAG9D,iCAAiC;;IAGjC,gDAAgD;;IAShD,oDAAoD;;IAQpD,sCAAsC;;IAStC,0CAA0C;;IAS1C,gDAAgD;;IAGhD,oEAAoE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASrE,CAAA;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE;;;GAGG;AACH,eAAO,MAAM,kBAAkB;IAC7B,sBAAsB;;IAGtB,sCAAsC;;IAGtC,kCAAkC;;IAGlC,iCAAiC;;IAGjC,mCAAmC;;IAGnC,8BAA8B;;IAG9B,mCAAmC;;IAGnC,6BAA6B;;IAG7B,2BAA2B;;IAG3B,4BAA4B;;IAG5B,4BAA4B;;IAG5B,iCAAiC;;IAGjC,8BAA8B;;IAG9B,4BAA4B;;IAG5B,sBAAsB;;IAGtB,2BAA2B;;IAG3B,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE3B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAElE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,GACd;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAA;CAAE,CAMrF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,GACd;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAA;CAAE,CAErF;AAWD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAS/D;AAsBD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CA6C5F"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,mDAAmD;AACnD,eAAO,MAAM,iBAAiB,6CAA2C,CAAA;AACzE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAS3D;;;GAGG;AACH,eAAO,MAAM,qBAAqB;IAE9B,oDAAoD;;IAUpD,4CAA4C;;IAE5C,sCAAsC;;IAEtC,wCAAwC;;IAIxC,wCAAwC;;IAExC,iDAAiD;;IAEjD,wCAAwC;;IAIxC,uCAAuC;;IAEvC,gDAAgD;;IAEhD,uCAAuC;;IAIvC,yCAAyC;;IAEzC,kDAAkD;;IAElD,yCAAyC;;IAIzC,wCAAwC;;IAExC,6CAA6C;;IAE7C,oCAAoC;;IAIpC,iDAAiD;;IAEjD,kDAAkD;;IAElD,yCAAyC;;IAGzC,2DAA2D;;IAS3D,mEAAmE;;IAGnE,8DAA8D;;IAG9D,iCAAiC;;IAGjC,gDAAgD;;IAShD,oDAAoD;;IAQpD,sCAAsC;;IAStC,0CAA0C;;IAS1C,gDAAgD;;IAGhD,oEAAoE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASrE,CAAA;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEnE;;;GAGG;AACH,eAAO,MAAM,kBAAkB;IAC7B,sBAAsB;;IAGtB,sCAAsC;;IAGtC,kCAAkC;;IAGlC,iCAAiC;;IAGjC,mCAAmC;;IAGnC,8BAA8B;;IAG9B,mCAAmC;;IAGnC,6BAA6B;;IAG7B,2BAA2B;;IAG3B,4BAA4B;;IAG5B,4BAA4B;;IAG5B,iCAAiC;;IAGjC,8BAA8B;;IAG9B,4BAA4B;;IAG5B,sBAAsB;;IAGtB,2BAA2B;;IAG3B,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE3B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAElE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,OAAO,GACd;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAA;CAAE,CAMrF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,CAE5D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,GACd;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAA;CAAE,CAErF;AAWD;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAS/D;AAsBD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CA6C5F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,eAAe,GAAG,YAAY,CAyDjF"}
package/dist/config.js CHANGED
@@ -8,7 +8,7 @@
8
8
  * 3. Command reference (e.g., apiKeyCommand: "op read op://...")
9
9
  */
10
10
  import { z } from 'zod';
11
- import { resolveSecret } from './secrets.js';
11
+ import { resolveSecret, resolveSecretSync } from './secrets.js';
12
12
  /** User scoping strategies for memory isolation */
13
13
  export const UserScopingSchema = z.enum(['agent', 'identity', 'session']);
14
14
  /**
@@ -284,4 +284,51 @@ export async function resolveConfigSecrets(rawConfig) {
284
284
  // Validate the resolved config
285
285
  return validateConfig(resolvedConfig);
286
286
  }
287
+ /**
288
+ * Resolves all secrets synchronously to produce a resolved config.
289
+ *
290
+ * Used during plugin registration where blocking I/O is acceptable.
291
+ * OpenClaw's loader does not await the register function, so all
292
+ * config resolution must complete synchronously.
293
+ *
294
+ * @param rawConfig - The raw plugin configuration with secret references
295
+ * @returns The resolved plugin configuration with actual secret values
296
+ * @throws If required secrets cannot be resolved
297
+ */
298
+ export function resolveConfigSecretsSync(rawConfig) {
299
+ const timeout = rawConfig.secretCommandTimeout;
300
+ // Resolve API key (required)
301
+ const apiKey = resolveSecretSync(buildSecretConfig(rawConfig, 'apiKey', timeout), 'apiKey');
302
+ if (!apiKey) {
303
+ throw new Error('Failed to resolve API key from config');
304
+ }
305
+ // Resolve optional secrets
306
+ const twilioAccountSid = resolveSecretSync(buildSecretConfig(rawConfig, 'twilioAccountSid', timeout), 'twilioAccountSid');
307
+ const twilioAuthToken = resolveSecretSync(buildSecretConfig(rawConfig, 'twilioAuthToken', timeout), 'twilioAuthToken');
308
+ const twilioPhoneNumber = resolveSecretSync(buildSecretConfig(rawConfig, 'twilioPhoneNumber', timeout), 'twilioPhoneNumber');
309
+ const postmarkToken = resolveSecretSync(buildSecretConfig(rawConfig, 'postmarkToken', timeout), 'postmarkToken');
310
+ const postmarkFromEmail = resolveSecretSync(buildSecretConfig(rawConfig, 'postmarkFromEmail', timeout), 'postmarkFromEmail');
311
+ // Build the resolved config
312
+ const resolvedConfig = {
313
+ apiUrl: rawConfig.apiUrl,
314
+ apiKey,
315
+ twilioAccountSid,
316
+ twilioAuthToken,
317
+ twilioPhoneNumber,
318
+ postmarkToken,
319
+ postmarkFromEmail,
320
+ secretCommandTimeout: timeout,
321
+ autoRecall: rawConfig.autoRecall,
322
+ autoCapture: rawConfig.autoCapture,
323
+ userScoping: rawConfig.userScoping,
324
+ maxRecallMemories: rawConfig.maxRecallMemories,
325
+ minRecallScore: rawConfig.minRecallScore,
326
+ timeout: rawConfig.timeout,
327
+ maxRetries: rawConfig.maxRetries,
328
+ debug: rawConfig.debug,
329
+ baseUrl: rawConfig.baseUrl,
330
+ };
331
+ // Validate the resolved config
332
+ return validateConfig(resolvedConfig);
333
+ }
287
334
  //# sourceMappingURL=config.js.map