clawdbot-penfield 1.0.1

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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +519 -0
  3. package/dist/index.d.ts +27 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +93 -0
  6. package/dist/src/api-client.d.ts +14 -0
  7. package/dist/src/api-client.d.ts.map +1 -0
  8. package/dist/src/api-client.js +53 -0
  9. package/dist/src/auth-service.d.ts +35 -0
  10. package/dist/src/auth-service.d.ts.map +1 -0
  11. package/dist/src/auth-service.js +197 -0
  12. package/dist/src/cli.d.ts +9 -0
  13. package/dist/src/cli.d.ts.map +1 -0
  14. package/dist/src/cli.js +50 -0
  15. package/dist/src/config.d.ts +16 -0
  16. package/dist/src/config.d.ts.map +1 -0
  17. package/dist/src/config.js +14 -0
  18. package/dist/src/device-flow.d.ts +35 -0
  19. package/dist/src/device-flow.d.ts.map +1 -0
  20. package/dist/src/device-flow.js +169 -0
  21. package/dist/src/runtime.d.ts +18 -0
  22. package/dist/src/runtime.d.ts.map +1 -0
  23. package/dist/src/runtime.js +18 -0
  24. package/dist/src/store.d.ts +49 -0
  25. package/dist/src/store.d.ts.map +1 -0
  26. package/dist/src/store.js +66 -0
  27. package/dist/src/tools/awaken.d.ts +4 -0
  28. package/dist/src/tools/awaken.d.ts.map +1 -0
  29. package/dist/src/tools/awaken.js +17 -0
  30. package/dist/src/tools/connect.d.ts +9 -0
  31. package/dist/src/tools/connect.d.ts.map +1 -0
  32. package/dist/src/tools/connect.js +41 -0
  33. package/dist/src/tools/delete-artifact.d.ts +6 -0
  34. package/dist/src/tools/delete-artifact.d.ts.map +1 -0
  35. package/dist/src/tools/delete-artifact.js +24 -0
  36. package/dist/src/tools/explore.d.ts +9 -0
  37. package/dist/src/tools/explore.d.ts.map +1 -0
  38. package/dist/src/tools/explore.js +35 -0
  39. package/dist/src/tools/fetch.d.ts +6 -0
  40. package/dist/src/tools/fetch.d.ts.map +1 -0
  41. package/dist/src/tools/fetch.js +21 -0
  42. package/dist/src/tools/index.d.ts +4 -0
  43. package/dist/src/tools/index.d.ts.map +1 -0
  44. package/dist/src/tools/index.js +58 -0
  45. package/dist/src/tools/list-artifacts.d.ts +7 -0
  46. package/dist/src/tools/list-artifacts.d.ts.map +1 -0
  47. package/dist/src/tools/list-artifacts.js +32 -0
  48. package/dist/src/tools/list-contexts.d.ts +7 -0
  49. package/dist/src/tools/list-contexts.d.ts.map +1 -0
  50. package/dist/src/tools/list-contexts.js +32 -0
  51. package/dist/src/tools/recall.d.ts +13 -0
  52. package/dist/src/tools/recall.d.ts.map +1 -0
  53. package/dist/src/tools/recall.js +64 -0
  54. package/dist/src/tools/reflect.d.ts +8 -0
  55. package/dist/src/tools/reflect.d.ts.map +1 -0
  56. package/dist/src/tools/reflect.js +38 -0
  57. package/dist/src/tools/restore-context.d.ts +8 -0
  58. package/dist/src/tools/restore-context.d.ts.map +1 -0
  59. package/dist/src/tools/restore-context.js +34 -0
  60. package/dist/src/tools/retrieve-artifact.d.ts +6 -0
  61. package/dist/src/tools/retrieve-artifact.d.ts.map +1 -0
  62. package/dist/src/tools/retrieve-artifact.js +24 -0
  63. package/dist/src/tools/save-artifact.d.ts +8 -0
  64. package/dist/src/tools/save-artifact.d.ts.map +1 -0
  65. package/dist/src/tools/save-artifact.js +27 -0
  66. package/dist/src/tools/save-context.d.ts +7 -0
  67. package/dist/src/tools/save-context.d.ts.map +1 -0
  68. package/dist/src/tools/save-context.js +27 -0
  69. package/dist/src/tools/search.d.ts +9 -0
  70. package/dist/src/tools/search.d.ts.map +1 -0
  71. package/dist/src/tools/search.js +41 -0
  72. package/dist/src/tools/store.d.ts +11 -0
  73. package/dist/src/tools/store.d.ts.map +1 -0
  74. package/dist/src/tools/store.js +36 -0
  75. package/dist/src/tools/update-memory.d.ts +11 -0
  76. package/dist/src/tools/update-memory.d.ts.map +1 -0
  77. package/dist/src/tools/update-memory.js +34 -0
  78. package/dist/src/types/typebox.d.ts +19 -0
  79. package/dist/src/types/typebox.d.ts.map +1 -0
  80. package/dist/src/types/typebox.js +91 -0
  81. package/dist/src/types.d.ts +73 -0
  82. package/dist/src/types.d.ts.map +1 -0
  83. package/dist/src/types.js +7 -0
  84. package/dist/src/validation.d.ts +21 -0
  85. package/dist/src/validation.d.ts.map +1 -0
  86. package/dist/src/validation.js +43 -0
  87. package/package.json +52 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 penfieldlabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,519 @@
1
+ # Penfield Memory for Clawdbot (clawdbot-penfield)
2
+
3
+ [![npm version](https://img.shields.io/npm/v/clawdbot-penfield.svg)](https://www.npmjs.com/package/clawdbot-penfield)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ **Persistent, searchable memory for [Clawdbot](https://clawd.bot).**
7
+
8
+ Your lobster remembers every conversation, learns your preferences, and builds knowledge over time—across all your channels.
9
+
10
+ ## 🦞 What is this?
11
+
12
+ A Clawdbot plugin that connects your agent to [Penfield](https://penfield.app), giving it:
13
+
14
+ - **Long-term memory** — Conversations persist forever, not just one session
15
+ - **Semantic search** — "What did I say about the Tokyo trip?" actually works
16
+ - **Knowledge graphs** — Memories connect to memories, building real understanding
17
+ - **Cross-channel recall** — Remember WhatsApp convos from Discord
18
+
19
+ ## 🚀 Quick Start
20
+
21
+ ```bash
22
+ clawdbot plugins install clawdbot-penfield
23
+ ```
24
+
25
+ ```bash
26
+ clawdbot penfield login
27
+ ```
28
+
29
+ Tell your Clawdbot to "Awaken with Penfield"
30
+
31
+ ## 🔑 Get Access
32
+
33
+ Penfield is in **free beta**. Sign up for access:
34
+
35
+ **👉 [accounts.penfield.app/waitlist](https://accounts.penfield.app/waitlist)**
36
+
37
+ ## Features
38
+
39
+ Native Clawdbot plugin providing direct integration with Penfield's memory and knowledge graph API. This plugin offers 4-5x performance improvement over the MCP server approach by eliminating the mcporter → MCP → Penfield stack.
40
+
41
+ - **16 Memory Tools**: Complete 1:1 feature parity with Penfield MCP server
42
+ - **OAuth Device Code Flow**: Secure authentication following RFC 8628
43
+ - **Automatic Token Refresh**: Transparent token management with 240-minute expiry buffer
44
+ - **Hybrid Search**: BM25 + vector + graph search capabilities
45
+ - **Knowledge Graph**: Build and traverse relationships between memories
46
+ - **Context Management**: Save and restore memory checkpoints
47
+ - **Artifact Storage**: Store and retrieve files in Penfield
48
+ - **Reflection & Analysis**: Analyze memory patterns and generate insights
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ clawdbot plugins install clawdbot-penfield
54
+ ```
55
+
56
+ ### From Source (for contributors)
57
+
58
+ ```bash
59
+ git clone https://github.com/penfieldlabs/clawdbot-penfield.git
60
+ cd clawdbot-penfield
61
+ npm install
62
+ npm run build
63
+ clawdbot plugins install -l .
64
+ ```
65
+
66
+ ## Configuration
67
+
68
+ The plugin is **auto-enabled when loaded**. No configuration required for production use.
69
+
70
+ **Default URLs (production):**
71
+ - API: `https://api.penfield.app`
72
+ - Auth: `https://auth.penfield.app`
73
+
74
+ **Override with environment variables (for development):**
75
+
76
+ ```bash
77
+ export PENFIELD_API_URL="https://api-dev.penfield.app"
78
+ export PENFIELD_AUTH_URL="https://auth-dev.penfield.app"
79
+ ```
80
+
81
+ **Or with config in `~/.clawdbot/clawdbot.json`:**
82
+
83
+ ```json
84
+ {
85
+ "plugins": {
86
+ "entries": {
87
+ "penfield": {
88
+ "enabled": true,
89
+ "config": {
90
+ "apiUrl": "https://api-dev.penfield.app",
91
+ "authUrl": "https://auth-dev.penfield.app"
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## Authentication
100
+
101
+ The plugin uses OAuth 2.0 Device Code Flow (RFC 8628) with automatic token refresh.
102
+
103
+ ### CLI Login
104
+
105
+ ```bash
106
+ clawdbot penfield login
107
+ ```
108
+
109
+ This will:
110
+ 1. Discover OAuth endpoints from the auth server
111
+ 2. Register a dynamic client (DCR) if needed
112
+ 3. Display a device code for user authentication
113
+ 4. Poll for token completion
114
+
115
+ ### Credentials
116
+
117
+ ```json
118
+ {
119
+ "version": 1,
120
+ "clientId": "dyn_abc123...",
121
+ "access": "eyJ...",
122
+ "refresh": "eyJ...",
123
+ "expires": 1234567890000,
124
+ "createdAt": 1234567890000
125
+ }
126
+ ```
127
+
128
+ Location: `~/.clawdbot/extensions/penfield/credentials.json`
129
+ File permissions: `0o600` (owner-only read/write)
130
+
131
+ ## Available Tools
132
+
133
+ ### Memory Management
134
+
135
+ #### `penfield_store`
136
+ Store a new memory in Penfield.
137
+
138
+ **Parameters:**
139
+ - `content` (required): Memory content (max 10,000 chars)
140
+ - `memory_type` (optional): Type of memory (default: "fact")
141
+ - Options: fact, insight, conversation, correction, reference, task, checkpoint, identity_core, personality_trait, relationship, strategy
142
+ - `importance` (optional): Score 0-1 (default: 0.5)
143
+ - `confidence` (optional): Score 0-1 (default: 0.8)
144
+ - `source_type` (optional): Source type (e.g., "direct_input", "conversation")
145
+ - `tags` (optional): Array of tags (max 10)
146
+
147
+ **Example:**
148
+ ```typescript
149
+ {
150
+ "content": "User prefers TypeScript over JavaScript",
151
+ "memory_type": "fact",
152
+ "importance": 0.7,
153
+ "tags": ["preferences", "programming"]
154
+ }
155
+ ```
156
+
157
+ #### `penfield_recall`
158
+ Hybrid search using BM25 + vector + graph.
159
+
160
+ **Parameters:**
161
+ - `query` (required): Search query (1-4,000 chars)
162
+ - `limit` (optional): Max results (default: 20, max: 100)
163
+ - `bm25_weight` (optional): Keyword weight (default: 0.4)
164
+ - `vector_weight` (optional): Semantic weight (default: 0.4)
165
+ - `graph_weight` (optional): Relationship weight (default: 0.2)
166
+ - `memory_types` (optional): Filter by types
167
+ - `importance_threshold` (optional): Minimum importance
168
+ - `enable_graph_expansion` (optional): Enable traversal (default: true)
169
+
170
+ **Example:**
171
+ ```typescript
172
+ {
173
+ "query": "programming preferences",
174
+ "limit": 10,
175
+ "vector_weight": 0.5,
176
+ "bm25_weight": 0.3,
177
+ "graph_weight": 0.2
178
+ }
179
+ ```
180
+
181
+ #### `penfield_search`
182
+ Semantic search variant (higher vector weight).
183
+
184
+ **Parameters:**
185
+ - `query` (required): Search query
186
+ - `limit` (optional): Max results
187
+ - `memory_types` (optional): Filter by types
188
+ - `importance_threshold` (optional): Minimum importance
189
+
190
+ #### `penfield_fetch`
191
+ Get a specific memory by ID.
192
+
193
+ **Parameters:**
194
+ - `memory_id` (required): Memory ID to fetch
195
+
196
+ #### `penfield_update_memory`
197
+ Update an existing memory.
198
+
199
+ **Parameters:**
200
+ - `memory_id` (required): Memory ID to update
201
+ - `content` (optional): Updated content
202
+ - `memory_type` (optional): Updated type
203
+ - `importance` (optional): Updated importance
204
+ - `confidence` (optional): Updated confidence
205
+ - `tags` (optional): Updated tags
206
+
207
+ ### Knowledge Graph
208
+
209
+ #### `penfield_connect`
210
+ Create a relationship between two memories.
211
+
212
+ **Parameters:**
213
+ - `from_memory_id` (required): Source memory ID
214
+ - `to_memory_id` (required): Target memory ID
215
+ - `relationship_type` (required): Type of relationship
216
+ - **Knowledge Evolution**: supersedes, updates, evolution_of
217
+ - **Evidence & Support**: supports, contradicts, disputes
218
+ - **Hierarchy & Structure**: parent_of, child_of, sibling_of, composed_of, part_of
219
+ - **Cause & Prerequisites**: causes, influenced_by, prerequisite_for
220
+ - **Implementation & Testing**: implements, documents, tests, example_of
221
+ - **Conversation & Attribution**: responds_to, references, inspired_by
222
+ - **Sequence & Flow**: follows, precedes
223
+ - **Dependencies**: depends_on
224
+ - `strength` (optional): Relationship strength 0-1 (default: 0.8)
225
+
226
+ **Example:**
227
+ ```typescript
228
+ {
229
+ "from_memory_id": "22618318-8d82-49c9-8bb8-1cf3a61b3c75",
230
+ "to_memory_id": "20413926-2446-4f88-bfd6-749b37969f34",
231
+ "relationship_type": "supports",
232
+ "strength": 0.9
233
+ }
234
+ ```
235
+
236
+ #### `penfield_explore`
237
+ Traverse the knowledge graph from a starting memory.
238
+
239
+ **Parameters:**
240
+ - `start_memory_id` (required): Starting memory ID
241
+ - `max_depth` (optional): Max traversal depth (default: 3, max: 10)
242
+ - `relationship_types` (optional): Filter by relationship types
243
+ - `min_strength` (optional): Minimum relationship strength
244
+
245
+ ### Context Management
246
+
247
+ #### `penfield_save_context`
248
+ Save a checkpoint of current memory state.
249
+
250
+ **Parameters:**
251
+ - `memory_ids` (required): Array of memory IDs to save
252
+ - `session_id` (optional): Session identifier
253
+
254
+ #### `penfield_restore_context`
255
+ Restore a previously saved checkpoint.
256
+
257
+ **Parameters:**
258
+ - `checkpoint_id` (required): Checkpoint ID to restore
259
+ - `full_restore` (optional): Create new copies of memories instead of referencing existing (default: false)
260
+ - `merge_mode` (optional): How to handle conflicts - "append", "replace", or "smart_merge" (default: "append")
261
+
262
+ #### `penfield_list_contexts`
263
+ List all saved checkpoints.
264
+
265
+ **Parameters:**
266
+ - `session_id` (optional): Filter by session ID
267
+ - `limit` (optional): Max results (default: 20, max: 100)
268
+
269
+ ### Analysis
270
+
271
+ #### `penfield_reflect`
272
+ Analyze memory patterns and generate insights.
273
+
274
+ **Parameters:**
275
+ - `time_window` (optional): Time window - "1d", "7d", "30d", or "90d" (default: "7d")
276
+ - `focus_areas` (optional): Areas to analyze - "memory_usage", "relationships", "importance", "topics", "patterns"
277
+ - `memory_types` (optional): Filter by memory types - "fact", "insight", "conversation", "correction", "reference", "task", "checkpoint", "identity_core", "personality_trait", "relationship", "strategy"
278
+
279
+ ### Artifact Storage
280
+
281
+ #### `penfield_save_artifact`
282
+ Save a file artifact to Penfield storage.
283
+
284
+ **Parameters:**
285
+ - `path` (required): Artifact path (e.g., "/project/file.txt")
286
+ - `content` (required): Artifact content
287
+ - `content_type` (optional): MIME type (default: "text/plain")
288
+
289
+ #### `penfield_retrieve_artifact`
290
+ Retrieve a file artifact from Penfield storage.
291
+
292
+ **Parameters:**
293
+ - `path` (required): Artifact path to retrieve
294
+
295
+ #### `penfield_list_artifacts`
296
+ List artifacts in a directory.
297
+
298
+ **Parameters:**
299
+ - `prefix` (optional): Directory prefix (e.g., "/project/")
300
+ - `limit` (optional): Max results (default: 100, max: 1000)
301
+
302
+ #### `penfield_delete_artifact`
303
+ Delete a file artifact from Penfield storage.
304
+
305
+ **Parameters:**
306
+ - `path` (required): Artifact path to delete
307
+
308
+ ### Personality
309
+
310
+ #### `penfield_awaken`
311
+ Load personality configuration and identity core memories.
312
+
313
+ **Parameters:** None
314
+
315
+ ## Usage Examples
316
+
317
+ ### Basic Memory Storage and Retrieval
318
+
319
+ ```typescript
320
+ // Store a memory
321
+ await penfield_store({
322
+ content: "User prefers dark mode for coding",
323
+ memory_type: "fact",
324
+ importance: 0.8,
325
+ tags: ["preferences", "ui"]
326
+ });
327
+
328
+ // Recall memories
329
+ const results = await penfield_recall({
330
+ query: "user interface preferences",
331
+ limit: 5
332
+ });
333
+ ```
334
+
335
+ ### Building Knowledge Graphs
336
+
337
+ ```typescript
338
+ // Store two related memories
339
+ const mem1 = await penfield_store({
340
+ content: "TypeScript provides static typing",
341
+ memory_type: "fact"
342
+ });
343
+
344
+ const mem2 = await penfield_store({
345
+ content: "Static typing helps catch bugs early",
346
+ memory_type: "insight"
347
+ });
348
+
349
+ // Connect them
350
+ await penfield_connect({
351
+ from_memory_id: mem1.id,
352
+ to_memory_id: mem2.id,
353
+ relationship_type: "supports",
354
+ strength: 0.9
355
+ });
356
+
357
+ // Explore the graph
358
+ const graph = await penfield_explore({
359
+ start_memory_id: mem1.id,
360
+ max_depth: 2
361
+ });
362
+ ```
363
+
364
+ ### Context Checkpoints
365
+
366
+ ```typescript
367
+ // Save context
368
+ const checkpoint = await penfield_save_context({
369
+ memory_ids: ["mem_1", "mem_2", "mem_3"],
370
+ session_id: "session_123"
371
+ });
372
+
373
+ // Restore later
374
+ await penfield_restore_context({
375
+ checkpoint_id: checkpoint.id,
376
+ full_restore: true
377
+ });
378
+ ```
379
+
380
+ ## Development
381
+
382
+ ### Setup
383
+
384
+ ```bash
385
+ npm install
386
+ ```
387
+
388
+ ### Type Check
389
+
390
+ ```bash
391
+ npm run typecheck
392
+ ```
393
+
394
+ ### Lint
395
+
396
+ ```bash
397
+ npm run lint
398
+ npm run lint:fix
399
+ ```
400
+
401
+ ### Format
402
+
403
+ ```bash
404
+ npm run format
405
+ npm run format:check
406
+ ```
407
+
408
+ ### Build
409
+
410
+ ```bash
411
+ npm run build
412
+ ```
413
+
414
+ ## Architecture
415
+
416
+ ```
417
+ index.ts # Plugin entry point and registration
418
+ src/
419
+ ├── config.ts # Zod configuration schema with DEFAULT_AUTH_URL/DEFAULT_API_URL
420
+ ├── types.ts # TypeScript type definitions (single source)
421
+ ├── types/typebox.ts # Centralized TypeBox exports
422
+ ├── auth-service.ts # Background OAuth token refresh service
423
+ ├── api-client.ts # HTTP client wrapper
424
+ ├── runtime.ts # Runtime factory (receives authService from index.ts)
425
+ ├── store.ts # Credential file I/O with TOKEN_EXPIRY_BUFFER_MS
426
+ ├── cli.ts # CLI command registration (penfield login)
427
+ ├── device-flow.ts # RFC 8628 Device Code Flow implementation
428
+ └── tools/
429
+ ├── index.ts # Tool registry (16 tools)
430
+ ├── store.ts # penfield_store
431
+ ├── recall.ts # penfield_recall
432
+ ├── search.ts # penfield_search
433
+ ├── fetch.ts # penfield_fetch
434
+ ├── update-memory.ts # penfield_update_memory
435
+ ├── connect.ts # penfield_connect
436
+ ├── explore.ts # penfield_explore
437
+ ├── save-context.ts # penfield_save_context
438
+ ├── restore-context.ts # penfield_restore_context
439
+ ├── list-contexts.ts # penfield_list_contexts
440
+ ├── reflect.ts # penfield_reflect
441
+ ├── save-artifact.ts # penfield_save_artifact
442
+ ├── retrieve-artifact.ts # penfield_retrieve_artifact
443
+ ├── list-artifacts.ts # penfield_list_artifacts
444
+ ├── delete-artifact.ts # penfield_delete_artifact
445
+ └── awaken.ts # penfield_awaken
446
+ ```
447
+
448
+ ## Service Lifecycle
449
+
450
+ The plugin uses two services registered with Clawdbot:
451
+
452
+ 1. **penfield-auth**: Background token refresh service
453
+ - Started when plugin loads
454
+ - Checks token expiry every 60 minutes
455
+ - Auto-refreshes if within 240-minute buffer
456
+
457
+ 2. **penfield**: Runtime lifecycle service
458
+ - Manages runtime initialization
459
+ - Handles cleanup on shutdown
460
+
461
+ ## API Endpoint Mapping
462
+
463
+ | Tool | Method | Endpoint |
464
+ |------|--------|----------|
465
+ | awaken | GET | /api/v2/personality/awakening |
466
+ | connect | POST | /api/v2/relationships |
467
+ | delete_artifact | DELETE | /api/v2/artifacts |
468
+ | explore | POST | /api/v2/relationships/traverse |
469
+ | fetch | GET | /api/v2/memories/{id} |
470
+ | list_artifacts | GET | /api/v2/artifacts/list |
471
+ | list_contexts | GET | /api/v2/checkpoint |
472
+ | recall | POST | /api/v2/search/hybrid |
473
+ | reflect | POST | /api/v2/analysis/reflect |
474
+ | restore_context | POST | /api/v2/checkpoint/{id}/recall |
475
+ | retrieve_artifact | GET | /api/v2/artifacts |
476
+ | save_artifact | POST | /api/v2/artifacts |
477
+ | save_context | POST | /api/v2/checkpoint/create |
478
+ | search | POST | /api/v2/search/hybrid |
479
+ | store | POST | /api/v2/memories |
480
+ | update_memory | PUT | /api/v2/memories/{id} |
481
+
482
+ ## Error Handling
483
+
484
+ All tools return errors in a consistent format:
485
+
486
+ ```json
487
+ {
488
+ "error": "Error message here"
489
+ }
490
+ ```
491
+
492
+ Common errors:
493
+ - **401 Unauthorized**: Token expired or invalid (auto-refreshes)
494
+ - **429 Rate Limited**: Too many requests (includes retry-after header)
495
+ - **500 Internal Server Error**: API error
496
+
497
+ ## Performance
498
+
499
+ This native plugin provides significant performance improvements over the MCP server approach:
500
+
501
+ - **4-5x faster**: Direct HTTP calls vs. mcporter → MCP → Penfield
502
+ - **Lower latency**: No intermediate proxy servers
503
+ - **Reduced overhead**: Fewer serialization/deserialization steps
504
+ - **Auto token refresh**: No re-authentication delays
505
+
506
+ ## Security
507
+
508
+ - Automatic token refresh 240 minutes before expiry
509
+ - RFC 8628 compliant Device Code Flow
510
+ - All API calls use HTTPS
511
+
512
+ ## License
513
+
514
+ MIT
515
+
516
+ ## Support
517
+
518
+ For issues or questions:
519
+ - GitHub Issues: https://github.com/penfieldlabs/clawdbot-penfield/issues
@@ -0,0 +1,27 @@
1
+ import { type PenfieldConfig } from "./src/config.js";
2
+ import type { ClawdbotPluginApi } from "./src/types.js";
3
+ declare const penfieldPlugin: {
4
+ id: string;
5
+ name: string;
6
+ description: string;
7
+ configSchema: {
8
+ parse(value: unknown): PenfieldConfig;
9
+ uiHints: {
10
+ enabled: {
11
+ label: string;
12
+ help: string;
13
+ };
14
+ authUrl: {
15
+ label: string;
16
+ help: string;
17
+ };
18
+ apiUrl: {
19
+ label: string;
20
+ help: string;
21
+ };
22
+ };
23
+ };
24
+ register(api: ClawdbotPluginApi): void;
25
+ };
26
+ export default penfieldPlugin;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAK9F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,QAAA,MAAM,cAAc;;;;;qBAMH,OAAO,GAAG,cAAc;;;;;;;;;;;;;;;;kBAuBzB,iBAAiB;CAkEhC,CAAC;AAEF,eAAe,cAAc,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,93 @@
1
+ import { DEFAULT_AUTH_URL, PenfieldConfigSchema } from "./src/config.js";
2
+ import { createPenfieldRuntime } from "./src/runtime.js";
3
+ import { registerPenfieldTools } from "./src/tools/index.js";
4
+ import { registerLoginCommand } from "./src/cli.js";
5
+ import { createAuthService } from "./src/auth-service.js";
6
+ const penfieldPlugin = {
7
+ id: "penfield",
8
+ name: "Penfield Memory",
9
+ description: "Native Penfield memory integration with 16 tools for knowledge management",
10
+ configSchema: {
11
+ parse(value) {
12
+ // Handle undefined/null when no config section exists
13
+ if (value === undefined || value === null) {
14
+ return {};
15
+ }
16
+ return PenfieldConfigSchema.parse(value);
17
+ },
18
+ uiHints: {
19
+ enabled: {
20
+ label: "Enable Penfield",
21
+ help: "Enable Penfield memory integration",
22
+ },
23
+ authUrl: {
24
+ label: "Auth URL",
25
+ help: "Penfield Auth service URL (default: https://auth.penfield.app)",
26
+ },
27
+ apiUrl: {
28
+ label: "API URL",
29
+ help: "Penfield API URL (default: https://api.penfield.app)",
30
+ },
31
+ },
32
+ },
33
+ register(api) {
34
+ const cfg = PenfieldConfigSchema.parse(api.pluginConfig ?? {});
35
+ const logger = api.logger;
36
+ // Runtime state - follows voice-call pattern
37
+ let runtimePromise = null;
38
+ let runtime = null;
39
+ // Create auth service (single instance)
40
+ const authUrl = cfg.authUrl || DEFAULT_AUTH_URL;
41
+ const authService = createAuthService(api, {
42
+ authUrl,
43
+ // clientId loaded from credentials on first login
44
+ });
45
+ // Lazy runtime initialization with race condition protection
46
+ const ensureRuntime = async () => {
47
+ if (runtime)
48
+ return runtime;
49
+ if (!runtimePromise) {
50
+ runtimePromise = createPenfieldRuntime({
51
+ api,
52
+ config: cfg,
53
+ authService,
54
+ logger,
55
+ });
56
+ }
57
+ runtime = await runtimePromise;
58
+ return runtime;
59
+ };
60
+ // Register CLI commands (penfield login)
61
+ registerLoginCommand(api);
62
+ // Register background auth service
63
+ api.registerService({
64
+ id: "penfield-auth",
65
+ async start() {
66
+ await authService.start();
67
+ logger.info("[penfield-auth] Service started");
68
+ },
69
+ async stop() {
70
+ await authService.stop();
71
+ logger.info("[penfield-auth] Service stopped");
72
+ },
73
+ });
74
+ // Register all 16 tools
75
+ registerPenfieldTools(api, ensureRuntime);
76
+ // Register service for runtime lifecycle
77
+ api.registerService({
78
+ id: "penfield",
79
+ async start() {
80
+ logger.info("[penfield] Service started");
81
+ },
82
+ async stop() {
83
+ if (runtime) {
84
+ await runtime.stop();
85
+ runtime = null;
86
+ runtimePromise = null;
87
+ }
88
+ logger.info("[penfield] Service stopped");
89
+ },
90
+ });
91
+ },
92
+ };
93
+ export default penfieldPlugin;
@@ -0,0 +1,14 @@
1
+ import type { AuthService } from "./auth-service.js";
2
+ import type { Logger } from "./types.js";
3
+ export declare class PenfieldApiClient {
4
+ private auth;
5
+ private apiUrl;
6
+ private logger?;
7
+ constructor(auth: AuthService, apiUrl: string, logger?: Logger | undefined);
8
+ request<T>(method: string, endpoint: string, body?: unknown, queryParams?: Record<string, string>): Promise<T>;
9
+ get<T>(endpoint: string, queryParams?: Record<string, string>): Promise<T>;
10
+ post<T>(endpoint: string, body?: unknown): Promise<T>;
11
+ put<T>(endpoint: string, body?: unknown): Promise<T>;
12
+ delete<T>(endpoint: string, queryParams?: Record<string, string>): Promise<T>;
13
+ }
14
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM,CAAC;gBAFP,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,YAAA;IAGnB,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,EACd,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,OAAO,CAAC,CAAC,CAAC;IAuCP,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAI1E,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIrD,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIpD,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAGpF"}