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
@@ -0,0 +1,49 @@
1
+ /**
2
+ * File-based credential storage for Penfield plugin
3
+ *
4
+ * Credentials are stored at: ~/.clawdbot/extensions/penfield/credentials.json
5
+ * Directory permissions: 0o700 (only owner can access)
6
+ * File permissions: 0o600 (only owner can read/write)
7
+ */
8
+ export declare const CRED_DIR = "~/.clawdbot/extensions/penfield";
9
+ export declare const CRED_FILE = "~/.clawdbot/extensions/penfield/credentials.json";
10
+ export declare const TOKEN_EXPIRY_BUFFER_MS: number;
11
+ export interface CredentialFile {
12
+ version: number;
13
+ clientId: string;
14
+ access: string;
15
+ refresh?: string;
16
+ expires: number;
17
+ createdAt: number;
18
+ }
19
+ /**
20
+ * Save credentials to file with schema versioning
21
+ */
22
+ export declare function saveCredential(api: {
23
+ resolvePath(path: string): string;
24
+ logger?: {
25
+ info(...args: unknown[]): void;
26
+ warn(...args: unknown[]): void;
27
+ error(...args: unknown[]): void;
28
+ };
29
+ }, cred: Omit<CredentialFile, 'version' | 'createdAt'>): void;
30
+ /**
31
+ * Load credentials from file
32
+ * Returns null if file doesn't exist or is corrupted
33
+ */
34
+ export declare function loadCredential(api: {
35
+ resolvePath(path: string): string;
36
+ }): CredentialFile | null;
37
+ /**
38
+ * Check if we have valid (non-expired) credentials
39
+ */
40
+ export declare function hasValidCredentials(api: {
41
+ resolvePath(path: string): string;
42
+ }): boolean;
43
+ /**
44
+ * Get refresh token if available
45
+ */
46
+ export declare function getRefreshToken(api: {
47
+ resolvePath(path: string): string;
48
+ }): string | null;
49
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,eAAO,MAAM,QAAQ,oCAAoC,CAAC;AAC1D,eAAO,MAAM,SAAS,qDAAiC,CAAC;AAGxD,eAAO,MAAM,sBAAsB,QAAkB,CAAC;AAEtD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE;IAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;KAAE,CAAA;CAAE,EACxJ,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,GAAG,WAAW,CAAC,GAClD,IAAI,CAiBN;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE;IAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GACzC,cAAc,GAAG,IAAI,CAevB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE;IAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GACzC,OAAO,CAMT;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE;IAAE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,GACzC,MAAM,GAAG,IAAI,CAGf"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * File-based credential storage for Penfield plugin
3
+ *
4
+ * Credentials are stored at: ~/.clawdbot/extensions/penfield/credentials.json
5
+ * Directory permissions: 0o700 (only owner can access)
6
+ * File permissions: 0o600 (only owner can read/write)
7
+ */
8
+ import * as fs from 'fs';
9
+ // Credential storage paths
10
+ export const CRED_DIR = '~/.clawdbot/extensions/penfield';
11
+ export const CRED_FILE = `${CRED_DIR}/credentials.json`;
12
+ // Token buffer: refresh if token expires within 240 minutes (4 hours)
13
+ export const TOKEN_EXPIRY_BUFFER_MS = 240 * 60 * 1000;
14
+ /**
15
+ * Save credentials to file with schema versioning
16
+ */
17
+ export function saveCredential(api, cred) {
18
+ const dirPath = api.resolvePath(CRED_DIR);
19
+ const filePath = api.resolvePath(CRED_FILE);
20
+ const content = {
21
+ version: 1,
22
+ ...cred,
23
+ createdAt: Date.now(),
24
+ };
25
+ // Create directory with restricted permissions (owner-only access)
26
+ fs.mkdirSync(dirPath, { recursive: true, mode: 0o700 });
27
+ // Atomic write: write to temp file, then rename (prevents corruption on crash)
28
+ const tmpPath = `${filePath}.tmp`;
29
+ fs.writeFileSync(tmpPath, JSON.stringify(content, null, 2), { mode: 0o600 });
30
+ fs.renameSync(tmpPath, filePath);
31
+ }
32
+ /**
33
+ * Load credentials from file
34
+ * Returns null if file doesn't exist or is corrupted
35
+ */
36
+ export function loadCredential(api) {
37
+ const filePath = api.resolvePath(CRED_FILE);
38
+ try {
39
+ const raw = fs.readFileSync(filePath, 'utf8');
40
+ const content = JSON.parse(raw);
41
+ if (content.version < 1) {
42
+ throw new Error('Unsupported credential version');
43
+ }
44
+ return content;
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ /**
51
+ * Check if we have valid (non-expired) credentials
52
+ */
53
+ export function hasValidCredentials(api) {
54
+ const cred = loadCredential(api);
55
+ if (!cred)
56
+ return false;
57
+ // Check if expired (with buffer)
58
+ return Date.now() < cred.expires - TOKEN_EXPIRY_BUFFER_MS;
59
+ }
60
+ /**
61
+ * Get refresh token if available
62
+ */
63
+ export function getRefreshToken(api) {
64
+ const cred = loadCredential(api);
65
+ return cred?.refresh || null;
66
+ }
@@ -0,0 +1,4 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const AwakenToolSchema: import("@sinclair/typebox").TObject<{}>;
3
+ export declare function executeAwakenTool(apiClient: PenfieldApiClient, _params: any): Promise<any>;
4
+ //# sourceMappingURL=awaken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"awaken.d.ts","sourceRoot":"","sources":["../../../src/tools/awaken.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,eAAO,MAAM,gBAAgB,yCAAmD,CAAC;AAEjF,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,GAAG,GACX,OAAO,CAAC,GAAG,CAAC,CAed"}
@@ -0,0 +1,17 @@
1
+ import { Type } from "../types/typebox.js";
2
+ export const AwakenToolSchema = Type.Object({}, { additionalProperties: false });
3
+ export async function executeAwakenTool(apiClient, _params // eslint-disable-line @typescript-eslint/no-explicit-any -- validated by TypeBox schema
4
+ ) {
5
+ // Awaken loads the user's personality briefing from the Penfield system
6
+ const response = await apiClient.get("/api/v2/personality/awakening");
7
+ const briefing = response.briefing || "";
8
+ return {
9
+ content: [
10
+ {
11
+ type: "text",
12
+ text: briefing,
13
+ },
14
+ ],
15
+ details: response,
16
+ };
17
+ }
@@ -0,0 +1,9 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const ConnectToolSchema: import("@sinclair/typebox").TObject<{
3
+ from_memory_id: import("@sinclair/typebox").TString;
4
+ to_memory_id: import("@sinclair/typebox").TString;
5
+ relationship_type: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"supersedes">, import("@sinclair/typebox").TLiteral<"updates">, import("@sinclair/typebox").TLiteral<"evolution_of">, import("@sinclair/typebox").TLiteral<"supports">, import("@sinclair/typebox").TLiteral<"contradicts">, import("@sinclair/typebox").TLiteral<"disputes">, import("@sinclair/typebox").TLiteral<"parent_of">, import("@sinclair/typebox").TLiteral<"child_of">, import("@sinclair/typebox").TLiteral<"sibling_of">, import("@sinclair/typebox").TLiteral<"causes">, import("@sinclair/typebox").TLiteral<"influenced_by">, import("@sinclair/typebox").TLiteral<"prerequisite_for">, import("@sinclair/typebox").TLiteral<"implements">, import("@sinclair/typebox").TLiteral<"documents">, import("@sinclair/typebox").TLiteral<"example_of">, import("@sinclair/typebox").TLiteral<"tests">, import("@sinclair/typebox").TLiteral<"responds_to">, import("@sinclair/typebox").TLiteral<"references">, import("@sinclair/typebox").TLiteral<"inspired_by">, import("@sinclair/typebox").TLiteral<"follows">, import("@sinclair/typebox").TLiteral<"precedes">, import("@sinclair/typebox").TLiteral<"depends_on">, import("@sinclair/typebox").TLiteral<"composed_of">, import("@sinclair/typebox").TLiteral<"part_of">]>;
6
+ strength: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
7
+ }>;
8
+ export declare function executeConnectTool(apiClient: PenfieldApiClient, params: any): Promise<any>;
9
+ //# sourceMappingURL=connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connect.d.ts","sourceRoot":"","sources":["../../../src/tools/connect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,eAAO,MAAM,iBAAiB;;;;;EAkBK,CAAC;AAEpC,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,GAAG,CAAC,CAsBd"}
@@ -0,0 +1,41 @@
1
+ import { Type, RelationshipTypeSchema } from "../types/typebox.js";
2
+ import { validateUuid } from "../validation.js";
3
+ export const ConnectToolSchema = Type.Object({
4
+ from_memory_id: Type.String({
5
+ description: "Source memory ID (UUID format)",
6
+ examples: ["22618318-8d82-49c9-8bb8-1cf3a61b3c75"],
7
+ }),
8
+ to_memory_id: Type.String({
9
+ description: "Target memory ID (UUID format)",
10
+ examples: ["20413926-2446-4f88-bfd6-749b37969f34"],
11
+ }),
12
+ relationship_type: RelationshipTypeSchema,
13
+ strength: Type.Optional(Type.Number({
14
+ description: "Relationship strength 0-1 (default: 0.8)",
15
+ minimum: 0,
16
+ maximum: 1,
17
+ default: 0.8,
18
+ })),
19
+ }, { additionalProperties: false });
20
+ export async function executeConnectTool(apiClient, params // eslint-disable-line @typescript-eslint/no-explicit-any -- validated by TypeBox schema
21
+ ) {
22
+ validateUuid(params.from_memory_id, 'from_memory_id');
23
+ validateUuid(params.to_memory_id, 'to_memory_id');
24
+ // Map user-friendly field names to API field names
25
+ const apiParams = {
26
+ from_id: params.from_memory_id,
27
+ to_id: params.to_memory_id,
28
+ relationship_type: params.relationship_type,
29
+ strength: params.strength,
30
+ };
31
+ const response = await apiClient.post("/api/v2/relationships", apiParams);
32
+ return {
33
+ content: [
34
+ {
35
+ type: "text",
36
+ text: JSON.stringify(response, null, 2),
37
+ },
38
+ ],
39
+ details: response,
40
+ };
41
+ }
@@ -0,0 +1,6 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const DeleteArtifactToolSchema: import("@sinclair/typebox").TObject<{
3
+ path: import("@sinclair/typebox").TString;
4
+ }>;
5
+ export declare function executeDeleteArtifactTool(apiClient: PenfieldApiClient, params: any): Promise<any>;
6
+ //# sourceMappingURL=delete-artifact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-artifact.d.ts","sourceRoot":"","sources":["../../../src/tools/delete-artifact.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,eAAO,MAAM,wBAAwB;;EAIF,CAAC;AAEpC,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,GAAG,CAAC,CAgBd"}
@@ -0,0 +1,24 @@
1
+ import { Type } from "../types/typebox.js";
2
+ import { validateArtifactPath } from "../validation.js";
3
+ export const DeleteArtifactToolSchema = Type.Object({
4
+ path: Type.String({
5
+ description: "Artifact path to delete",
6
+ }),
7
+ }, { additionalProperties: false });
8
+ export async function executeDeleteArtifactTool(apiClient, params // eslint-disable-line @typescript-eslint/no-explicit-any -- validated by TypeBox schema
9
+ ) {
10
+ validateArtifactPath(params.path);
11
+ const queryParams = {
12
+ path: params.path,
13
+ };
14
+ const response = await apiClient.delete("/api/v2/artifacts", queryParams);
15
+ return {
16
+ content: [
17
+ {
18
+ type: "text",
19
+ text: JSON.stringify(response, null, 2),
20
+ },
21
+ ],
22
+ details: response,
23
+ };
24
+ }
@@ -0,0 +1,9 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const ExploreToolSchema: import("@sinclair/typebox").TObject<{
3
+ start_memory_id: import("@sinclair/typebox").TString;
4
+ max_depth: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
5
+ relationship_types: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"supersedes">, import("@sinclair/typebox").TLiteral<"updates">, import("@sinclair/typebox").TLiteral<"evolution_of">, import("@sinclair/typebox").TLiteral<"supports">, import("@sinclair/typebox").TLiteral<"contradicts">, import("@sinclair/typebox").TLiteral<"disputes">, import("@sinclair/typebox").TLiteral<"parent_of">, import("@sinclair/typebox").TLiteral<"child_of">, import("@sinclair/typebox").TLiteral<"sibling_of">, import("@sinclair/typebox").TLiteral<"causes">, import("@sinclair/typebox").TLiteral<"influenced_by">, import("@sinclair/typebox").TLiteral<"prerequisite_for">, import("@sinclair/typebox").TLiteral<"implements">, import("@sinclair/typebox").TLiteral<"documents">, import("@sinclair/typebox").TLiteral<"example_of">, import("@sinclair/typebox").TLiteral<"tests">, import("@sinclair/typebox").TLiteral<"responds_to">, import("@sinclair/typebox").TLiteral<"references">, import("@sinclair/typebox").TLiteral<"inspired_by">, import("@sinclair/typebox").TLiteral<"follows">, import("@sinclair/typebox").TLiteral<"precedes">, import("@sinclair/typebox").TLiteral<"depends_on">, import("@sinclair/typebox").TLiteral<"composed_of">, import("@sinclair/typebox").TLiteral<"part_of">]>>>;
6
+ min_strength: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
7
+ }>;
8
+ export declare function executeExploreTool(apiClient: PenfieldApiClient, params: unknown): Promise<any>;
9
+ //# sourceMappingURL=explore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../../src/tools/explore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,eAAO,MAAM,iBAAiB;;;;;EAwBK,CAAC;AAEpC,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,GAAG,CAAC,CAcd"}
@@ -0,0 +1,35 @@
1
+ import { Type, RelationshipTypeSchema } from "../types/typebox.js";
2
+ import { validateUuid } from "../validation.js";
3
+ export const ExploreToolSchema = Type.Object({
4
+ start_memory_id: Type.String({
5
+ description: "Starting memory ID for graph traversal",
6
+ }),
7
+ max_depth: Type.Optional(Type.Number({
8
+ description: "Maximum traversal depth (default: 3, max: 10)",
9
+ minimum: 1,
10
+ maximum: 10,
11
+ default: 3,
12
+ })),
13
+ relationship_types: Type.Optional(Type.Array(RelationshipTypeSchema, {
14
+ description: "Filter by relationship types",
15
+ })),
16
+ min_strength: Type.Optional(Type.Number({
17
+ description: "Minimum relationship strength (0-1)",
18
+ minimum: 0,
19
+ maximum: 1,
20
+ })),
21
+ }, { additionalProperties: false });
22
+ export async function executeExploreTool(apiClient, params) {
23
+ const { start_memory_id } = params;
24
+ validateUuid(start_memory_id, 'start_memory_id');
25
+ const response = await apiClient.post("/api/v2/relationships/traverse", params);
26
+ return {
27
+ content: [
28
+ {
29
+ type: "text",
30
+ text: JSON.stringify(response, null, 2),
31
+ },
32
+ ],
33
+ details: response,
34
+ };
35
+ }
@@ -0,0 +1,6 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const FetchToolSchema: import("@sinclair/typebox").TObject<{
3
+ memory_id: import("@sinclair/typebox").TString;
4
+ }>;
5
+ export declare function executeFetchTool(apiClient: PenfieldApiClient, params: any): Promise<any>;
6
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/tools/fetch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1D,eAAO,MAAM,eAAe;;EAIO,CAAC;AAEpC,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,GAAG,CAAC,CAYd"}
@@ -0,0 +1,21 @@
1
+ import { Type } from "../types/typebox.js";
2
+ import { validateUuid } from "../validation.js";
3
+ export const FetchToolSchema = Type.Object({
4
+ memory_id: Type.String({
5
+ description: "Memory ID to fetch",
6
+ }),
7
+ }, { additionalProperties: false });
8
+ export async function executeFetchTool(apiClient, params // eslint-disable-line @typescript-eslint/no-explicit-any -- validated by TypeBox schema
9
+ ) {
10
+ validateUuid(params.memory_id, 'memory_id');
11
+ const response = await apiClient.get(`/api/v2/memories/${params.memory_id}`);
12
+ return {
13
+ content: [
14
+ {
15
+ type: "text",
16
+ text: JSON.stringify(response, null, 2),
17
+ },
18
+ ],
19
+ details: response,
20
+ };
21
+ }
@@ -0,0 +1,4 @@
1
+ import type { PenfieldRuntime } from "../runtime.js";
2
+ import type { ClawdbotPluginApi } from "../types.js";
3
+ export declare function registerPenfieldTools(api: ClawdbotPluginApi, ensureRuntime: () => Promise<PenfieldRuntime>): void;
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA6BrD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,iBAAiB,EACtB,aAAa,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,QAgK9C"}
@@ -0,0 +1,58 @@
1
+ import { StoreToolSchema, executeStoreTool } from "./store.js";
2
+ import { RecallToolSchema, executeRecallTool } from "./recall.js";
3
+ import { SearchToolSchema, executeSearchTool } from "./search.js";
4
+ import { FetchToolSchema, executeFetchTool } from "./fetch.js";
5
+ import { UpdateMemoryToolSchema, executeUpdateMemoryTool } from "./update-memory.js";
6
+ import { ConnectToolSchema, executeConnectTool } from "./connect.js";
7
+ import { ExploreToolSchema, executeExploreTool } from "./explore.js";
8
+ import { SaveContextToolSchema, executeSaveContextTool } from "./save-context.js";
9
+ import { RestoreContextToolSchema, executeRestoreContextTool, } from "./restore-context.js";
10
+ import { ListContextsToolSchema, executeListContextsTool } from "./list-contexts.js";
11
+ import { ReflectToolSchema, executeReflectTool } from "./reflect.js";
12
+ import { SaveArtifactToolSchema, executeSaveArtifactTool } from "./save-artifact.js";
13
+ import { RetrieveArtifactToolSchema, executeRetrieveArtifactTool, } from "./retrieve-artifact.js";
14
+ import { ListArtifactsToolSchema, executeListArtifactsTool } from "./list-artifacts.js";
15
+ import { DeleteArtifactToolSchema, executeDeleteArtifactTool, } from "./delete-artifact.js";
16
+ import { AwakenToolSchema, executeAwakenTool } from "./awaken.js";
17
+ export function registerPenfieldTools(api, ensureRuntime) {
18
+ const json = (payload) => ({
19
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
20
+ details: payload,
21
+ });
22
+ const registerTool = (name, label, description, schema, execute) => {
23
+ api.registerTool({
24
+ name,
25
+ label,
26
+ description,
27
+ parameters: schema,
28
+ async execute(_toolCallId, params) {
29
+ try {
30
+ const rt = await ensureRuntime();
31
+ return await execute(rt.apiClient, params);
32
+ }
33
+ catch (err) {
34
+ return json({
35
+ error: err instanceof Error ? err.message : String(err),
36
+ });
37
+ }
38
+ },
39
+ });
40
+ };
41
+ // Register all 16 tools
42
+ registerTool("penfield_store", "Store Memory", "Store a new memory in Penfield", StoreToolSchema, executeStoreTool);
43
+ registerTool("penfield_recall", "Recall Memories", "Search memories using hybrid BM25 + vector + graph search", RecallToolSchema, executeRecallTool);
44
+ registerTool("penfield_search", "Search Memories", "Semantic search for memories", SearchToolSchema, executeSearchTool);
45
+ registerTool("penfield_fetch", "Fetch Memory", "Get a specific memory by ID", FetchToolSchema, executeFetchTool);
46
+ registerTool("penfield_update_memory", "Update Memory", "Update an existing memory", UpdateMemoryToolSchema, executeUpdateMemoryTool);
47
+ registerTool("penfield_connect", "Connect Memories", "Create a relationship between two memories", ConnectToolSchema, executeConnectTool);
48
+ registerTool("penfield_explore", "Explore Graph", "Traverse the knowledge graph from a starting memory", ExploreToolSchema, executeExploreTool);
49
+ registerTool("penfield_save_context", "Save Context", "Save a checkpoint of current memory state", SaveContextToolSchema, executeSaveContextTool);
50
+ registerTool("penfield_restore_context", "Restore Context", "Restore a previously saved checkpoint", RestoreContextToolSchema, executeRestoreContextTool);
51
+ registerTool("penfield_list_contexts", "List Contexts", "List all saved checkpoints", ListContextsToolSchema, executeListContextsTool);
52
+ registerTool("penfield_reflect", "Reflect", "Analyze memory patterns and generate insights", ReflectToolSchema, executeReflectTool);
53
+ registerTool("penfield_save_artifact", "Save Artifact", "Save a file artifact to Penfield storage", SaveArtifactToolSchema, executeSaveArtifactTool);
54
+ registerTool("penfield_retrieve_artifact", "Retrieve Artifact", "Retrieve a file artifact from Penfield storage", RetrieveArtifactToolSchema, executeRetrieveArtifactTool);
55
+ registerTool("penfield_list_artifacts", "List Artifacts", "List artifacts in a directory", ListArtifactsToolSchema, executeListArtifactsTool);
56
+ registerTool("penfield_delete_artifact", "Delete Artifact", "Delete a file artifact from Penfield storage", DeleteArtifactToolSchema, executeDeleteArtifactTool);
57
+ registerTool("penfield_awaken", "Awaken", "Load personality configuration and identity core", AwakenToolSchema, executeAwakenTool);
58
+ }
@@ -0,0 +1,7 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const ListArtifactsToolSchema: import("@sinclair/typebox").TObject<{
3
+ prefix: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
4
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
5
+ }>;
6
+ export declare function executeListArtifactsTool(apiClient: PenfieldApiClient, params: any): Promise<any>;
7
+ //# sourceMappingURL=list-artifacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-artifacts.d.ts","sourceRoot":"","sources":["../../../src/tools/list-artifacts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,eAAO,MAAM,uBAAuB;;;EAcD,CAAC;AAEpC,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,GAAG,CAAC,CAmBd"}
@@ -0,0 +1,32 @@
1
+ import { Type } from "../types/typebox.js";
2
+ export const ListArtifactsToolSchema = Type.Object({
3
+ prefix: Type.Optional(Type.String({
4
+ description: "Directory prefix to list (e.g., /project/)",
5
+ })),
6
+ limit: Type.Optional(Type.Number({
7
+ description: "Max results (default: 100)",
8
+ minimum: 1,
9
+ maximum: 1000,
10
+ default: 100,
11
+ })),
12
+ }, { additionalProperties: false });
13
+ export async function executeListArtifactsTool(apiClient, params // eslint-disable-line @typescript-eslint/no-explicit-any -- validated by TypeBox schema
14
+ ) {
15
+ const queryParams = {};
16
+ if (params.prefix) {
17
+ queryParams.prefix = params.prefix;
18
+ }
19
+ if (params.limit) {
20
+ queryParams.limit = String(params.limit);
21
+ }
22
+ const response = await apiClient.get("/api/v2/artifacts/list", queryParams);
23
+ return {
24
+ content: [
25
+ {
26
+ type: "text",
27
+ text: JSON.stringify(response, null, 2),
28
+ },
29
+ ],
30
+ details: response,
31
+ };
32
+ }
@@ -0,0 +1,7 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const ListContextsToolSchema: import("@sinclair/typebox").TObject<{
3
+ session_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
4
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
5
+ }>;
6
+ export declare function executeListContextsTool(apiClient: PenfieldApiClient, params: any): Promise<any>;
7
+ //# sourceMappingURL=list-contexts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-contexts.d.ts","sourceRoot":"","sources":["../../../src/tools/list-contexts.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,eAAO,MAAM,sBAAsB;;;EAcA,CAAC;AAEpC,wBAAsB,uBAAuB,CAC3C,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,GAAG,CAAC,CAmBd"}
@@ -0,0 +1,32 @@
1
+ import { Type } from "../types/typebox.js";
2
+ export const ListContextsToolSchema = Type.Object({
3
+ session_id: Type.Optional(Type.String({
4
+ description: "Filter by session ID",
5
+ })),
6
+ limit: Type.Optional(Type.Number({
7
+ description: "Max results (default: 20, max: 100)",
8
+ minimum: 1,
9
+ maximum: 100,
10
+ default: 20,
11
+ })),
12
+ }, { additionalProperties: false });
13
+ export async function executeListContextsTool(apiClient, params // eslint-disable-line @typescript-eslint/no-explicit-any -- validated by TypeBox schema
14
+ ) {
15
+ const queryParams = {};
16
+ if (params.session_id) {
17
+ queryParams.session_id = params.session_id;
18
+ }
19
+ if (params.limit) {
20
+ queryParams.limit = String(params.limit);
21
+ }
22
+ const response = await apiClient.get("/api/v2/checkpoint", queryParams);
23
+ return {
24
+ content: [
25
+ {
26
+ type: "text",
27
+ text: JSON.stringify(response, null, 2),
28
+ },
29
+ ],
30
+ details: response,
31
+ };
32
+ }
@@ -0,0 +1,13 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const RecallToolSchema: import("@sinclair/typebox").TObject<{
3
+ query: import("@sinclair/typebox").TString;
4
+ limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
5
+ bm25_weight: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
6
+ vector_weight: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
7
+ graph_weight: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
8
+ memory_types: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"fact">, import("@sinclair/typebox").TLiteral<"insight">, import("@sinclair/typebox").TLiteral<"conversation">, import("@sinclair/typebox").TLiteral<"correction">, import("@sinclair/typebox").TLiteral<"reference">, import("@sinclair/typebox").TLiteral<"task">, import("@sinclair/typebox").TLiteral<"checkpoint">, import("@sinclair/typebox").TLiteral<"identity_core">, import("@sinclair/typebox").TLiteral<"personality_trait">, import("@sinclair/typebox").TLiteral<"relationship">, import("@sinclair/typebox").TLiteral<"strategy">]>>>;
9
+ importance_threshold: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
10
+ enable_graph_expansion: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
11
+ }>;
12
+ export declare function executeRecallTool(apiClient: PenfieldApiClient, params: any): Promise<any>;
13
+ //# sourceMappingURL=recall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recall.d.ts","sourceRoot":"","sources":["../../../src/tools/recall.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,eAAO,MAAM,gBAAgB;;;;;;;;;EAuDM,CAAC;AAEpC,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,GAAG,GACV,OAAO,CAAC,GAAG,CAAC,CAqBd"}
@@ -0,0 +1,64 @@
1
+ import { Type, MemoryTypeSchema, ImportanceScoreSchema } from "../types/typebox.js";
2
+ export const RecallToolSchema = Type.Object({
3
+ query: Type.String({
4
+ description: "Search query (1-4,000 chars)",
5
+ minLength: 1,
6
+ maxLength: 4000,
7
+ }),
8
+ limit: Type.Optional(Type.Number({
9
+ description: "Max results (default: 20, max: 100)",
10
+ minimum: 1,
11
+ maximum: 100,
12
+ default: 20,
13
+ })),
14
+ bm25_weight: Type.Optional(Type.Number({
15
+ description: "BM25 keyword weight (default: 0.4)",
16
+ minimum: 0,
17
+ maximum: 1,
18
+ default: 0.4,
19
+ })),
20
+ vector_weight: Type.Optional(Type.Number({
21
+ description: "Vector semantic weight (default: 0.4)",
22
+ minimum: 0,
23
+ maximum: 1,
24
+ default: 0.4,
25
+ })),
26
+ graph_weight: Type.Optional(Type.Number({
27
+ description: "Graph relationship weight (default: 0.2)",
28
+ minimum: 0,
29
+ maximum: 1,
30
+ default: 0.2,
31
+ })),
32
+ memory_types: Type.Optional(Type.Array(MemoryTypeSchema, {
33
+ description: "Filter by memory types",
34
+ })),
35
+ importance_threshold: Type.Optional(Type.Number({
36
+ ...ImportanceScoreSchema,
37
+ description: "Minimum importance (0-1)",
38
+ })),
39
+ enable_graph_expansion: Type.Optional(Type.Boolean({
40
+ description: "Enable graph traversal (default: true)",
41
+ default: true,
42
+ })),
43
+ }, { additionalProperties: false });
44
+ export async function executeRecallTool(apiClient, params // eslint-disable-line @typescript-eslint/no-explicit-any -- validated by TypeBox schema
45
+ ) {
46
+ // Validate weights sum to 1.0
47
+ const bm25 = params.bm25_weight ?? 0.4;
48
+ const vector = params.vector_weight ?? 0.4;
49
+ const graph = params.graph_weight ?? 0.2;
50
+ const sum = bm25 + vector + graph;
51
+ if (Math.abs(sum - 1.0) > 0.01) {
52
+ throw new Error(`Weights must sum to 1.0 (got ${sum})`);
53
+ }
54
+ const response = await apiClient.post("/api/v2/search/hybrid", params);
55
+ return {
56
+ content: [
57
+ {
58
+ type: "text",
59
+ text: JSON.stringify(response, null, 2),
60
+ },
61
+ ],
62
+ details: response,
63
+ };
64
+ }
@@ -0,0 +1,8 @@
1
+ import type { PenfieldApiClient } from "../api-client.js";
2
+ export declare const ReflectToolSchema: import("@sinclair/typebox").TObject<{
3
+ time_window: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"1d">, import("@sinclair/typebox").TLiteral<"7d">, import("@sinclair/typebox").TLiteral<"30d">, import("@sinclair/typebox").TLiteral<"90d">]>>;
4
+ focus_areas: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"memory_usage">, import("@sinclair/typebox").TLiteral<"relationships">, import("@sinclair/typebox").TLiteral<"importance">, import("@sinclair/typebox").TLiteral<"topics">, import("@sinclair/typebox").TLiteral<"patterns">]>>>;
5
+ memory_types: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"fact">, import("@sinclair/typebox").TLiteral<"insight">, import("@sinclair/typebox").TLiteral<"conversation">, import("@sinclair/typebox").TLiteral<"correction">, import("@sinclair/typebox").TLiteral<"reference">, import("@sinclair/typebox").TLiteral<"task">, import("@sinclair/typebox").TLiteral<"checkpoint">, import("@sinclair/typebox").TLiteral<"identity_core">, import("@sinclair/typebox").TLiteral<"personality_trait">, import("@sinclair/typebox").TLiteral<"relationship">, import("@sinclair/typebox").TLiteral<"strategy">]>>>;
6
+ }>;
7
+ export declare function executeReflectTool(apiClient: PenfieldApiClient, params: unknown): Promise<any>;
8
+ //# sourceMappingURL=reflect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reflect.d.ts","sourceRoot":"","sources":["../../../src/tools/reflect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,eAAO,MAAM,iBAAiB;;;;EAoCK,CAAC;AAEpC,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,GAAG,CAAC,CAWd"}
@@ -0,0 +1,38 @@
1
+ import { Type, MemoryTypeSchema } from "../types/typebox.js";
2
+ export const ReflectToolSchema = Type.Object({
3
+ time_window: Type.Optional(Type.Union([
4
+ Type.Literal("1d"),
5
+ Type.Literal("7d"),
6
+ Type.Literal("30d"),
7
+ Type.Literal("90d"),
8
+ ], {
9
+ description: "Time period to analyze. Defaults to last 7 days.",
10
+ examples: ["7d", "30d"],
11
+ })),
12
+ focus_areas: Type.Optional(Type.Array(Type.Union([
13
+ Type.Literal("memory_usage"),
14
+ Type.Literal("relationships"),
15
+ Type.Literal("importance"),
16
+ Type.Literal("topics"),
17
+ Type.Literal("patterns"),
18
+ ]), {
19
+ description: "Areas to focus analysis on. Omit for full analysis.",
20
+ examples: [["memory_usage", "relationships"], ["topics"]],
21
+ })),
22
+ memory_types: Type.Optional(Type.Array(MemoryTypeSchema, {
23
+ description: "Filter by memory types. Defaults to all types.",
24
+ examples: [["fact", "insight"], ["identity_core", "personality_trait"]],
25
+ })),
26
+ }, { additionalProperties: false });
27
+ export async function executeReflectTool(apiClient, params) {
28
+ const response = await apiClient.post("/api/v2/analysis/reflect", params);
29
+ return {
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: JSON.stringify(response, null, 2),
34
+ },
35
+ ],
36
+ details: response,
37
+ };
38
+ }