@memoryrelay/plugin-memoryrelay-ai 0.15.6 → 0.16.0
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 +2 -3
- package/index.ts +472 -4849
- package/openclaw.plugin.json +41 -3
- package/package.json +1 -1
- package/skills/decision-tracking/SKILL.md +1 -1
- package/skills/entity-and-context/SKILL.md +1 -1
- package/skills/memory-workflow/SKILL.md +1 -1
- package/src/client/memoryrelay-client.ts +816 -0
- package/src/context/namespace-router.ts +19 -0
- package/src/context/request-context.ts +39 -0
- package/src/context/session-resolver.ts +93 -0
- package/src/filters/content-patterns.ts +32 -0
- package/src/filters/noise-patterns.ts +33 -0
- package/src/filters/non-interactive.ts +30 -0
- package/src/hooks/activity.ts +51 -0
- package/src/hooks/agent-end.ts +48 -0
- package/src/hooks/before-agent-start.ts +109 -0
- package/src/hooks/before-prompt-build.ts +46 -0
- package/src/hooks/compaction.ts +51 -0
- package/src/hooks/privacy.ts +44 -0
- package/src/hooks/session-lifecycle.ts +47 -0
- package/src/hooks/subagent.ts +62 -0
- package/src/pipelines/capture/content-strip.ts +14 -0
- package/src/pipelines/capture/dedup.ts +17 -0
- package/src/pipelines/capture/index.ts +13 -0
- package/src/pipelines/capture/message-filter.ts +16 -0
- package/src/pipelines/capture/store.ts +33 -0
- package/src/pipelines/capture/trigger-gate.ts +21 -0
- package/src/pipelines/capture/truncate.ts +16 -0
- package/src/pipelines/recall/format.ts +30 -0
- package/src/pipelines/recall/index.ts +12 -0
- package/src/pipelines/recall/rank.ts +40 -0
- package/src/pipelines/recall/scope-resolver.ts +20 -0
- package/src/pipelines/recall/search.ts +43 -0
- package/src/pipelines/recall/trigger-gate.ts +17 -0
- package/src/pipelines/runner.ts +25 -0
- package/src/pipelines/types.ts +157 -0
- package/src/tools/agent-tools.ts +127 -0
- package/src/tools/decision-tools.ts +309 -0
- package/src/tools/entity-tools.ts +215 -0
- package/src/tools/health-tools.ts +42 -0
- package/src/tools/memory-tools.ts +690 -0
- package/src/tools/pattern-tools.ts +250 -0
- package/src/tools/project-tools.ts +444 -0
- package/src/tools/session-tools.ts +195 -0
- package/src/tools/v2-tools.ts +228 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
import type { PluginConfig } from "../pipelines/types.js";
|
|
3
|
+
import type { MemoryRelayClient } from "../client/memoryrelay-client.js";
|
|
4
|
+
|
|
5
|
+
export function registerPatternTools(
|
|
6
|
+
api: OpenClawPluginApi,
|
|
7
|
+
config: PluginConfig,
|
|
8
|
+
client: MemoryRelayClient,
|
|
9
|
+
isToolEnabled: (name: string) => boolean,
|
|
10
|
+
): void {
|
|
11
|
+
const defaultProject = config.defaultProject;
|
|
12
|
+
|
|
13
|
+
// --------------------------------------------------------------------------
|
|
14
|
+
// 25. pattern_create
|
|
15
|
+
// --------------------------------------------------------------------------
|
|
16
|
+
if (isToolEnabled("pattern_create")) {
|
|
17
|
+
api.registerTool((ctx) => ({
|
|
18
|
+
|
|
19
|
+
name: "pattern_create",
|
|
20
|
+
description:
|
|
21
|
+
"Create a reusable pattern (coding convention, architecture pattern, or best practice) that can be shared across projects. Include example_code for maximum usefulness." +
|
|
22
|
+
(defaultProject ? ` Source project defaults to '${defaultProject}' if not specified.` : ""),
|
|
23
|
+
parameters: {
|
|
24
|
+
type: "object",
|
|
25
|
+
properties: {
|
|
26
|
+
title: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "Pattern title.",
|
|
29
|
+
},
|
|
30
|
+
description: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "Detailed description of the pattern, when to use it, and why.",
|
|
33
|
+
},
|
|
34
|
+
category: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "Category (e.g., architecture, testing, error-handling, naming).",
|
|
37
|
+
},
|
|
38
|
+
example_code: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "Example code demonstrating the pattern.",
|
|
41
|
+
},
|
|
42
|
+
scope: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "Scope: global (visible to all projects) or project (visible to source project only).",
|
|
45
|
+
enum: ["global", "project"],
|
|
46
|
+
},
|
|
47
|
+
tags: {
|
|
48
|
+
type: "array",
|
|
49
|
+
description: "Tags for categorization.",
|
|
50
|
+
items: { type: "string" },
|
|
51
|
+
},
|
|
52
|
+
source_project: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Project slug where this pattern originated.",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
required: ["title", "description"],
|
|
58
|
+
},
|
|
59
|
+
execute: async (
|
|
60
|
+
_id,
|
|
61
|
+
args: {
|
|
62
|
+
title: string;
|
|
63
|
+
description: string;
|
|
64
|
+
category?: string;
|
|
65
|
+
example_code?: string;
|
|
66
|
+
scope?: string;
|
|
67
|
+
tags?: string[];
|
|
68
|
+
source_project?: string;
|
|
69
|
+
},
|
|
70
|
+
) => {
|
|
71
|
+
try {
|
|
72
|
+
const sourceProject = args.source_project ?? defaultProject;
|
|
73
|
+
const result = await client.createPattern(
|
|
74
|
+
args.title,
|
|
75
|
+
args.description,
|
|
76
|
+
args.category,
|
|
77
|
+
args.example_code,
|
|
78
|
+
args.scope,
|
|
79
|
+
args.tags,
|
|
80
|
+
sourceProject,
|
|
81
|
+
);
|
|
82
|
+
return {
|
|
83
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
84
|
+
details: { result },
|
|
85
|
+
};
|
|
86
|
+
} catch (err) {
|
|
87
|
+
return {
|
|
88
|
+
content: [{ type: "text", text: `Failed to create pattern: ${String(err)}` }],
|
|
89
|
+
details: { error: String(err) },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
}),
|
|
94
|
+
{ name: "pattern_create" },
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// --------------------------------------------------------------------------
|
|
99
|
+
// 26. pattern_search
|
|
100
|
+
// --------------------------------------------------------------------------
|
|
101
|
+
if (isToolEnabled("pattern_search")) {
|
|
102
|
+
api.registerTool((ctx) => ({
|
|
103
|
+
|
|
104
|
+
name: "pattern_search",
|
|
105
|
+
description: "Search for established patterns by natural language query. Call this before writing code to find and follow existing conventions." +
|
|
106
|
+
(defaultProject ? ` Scoped to project '${defaultProject}' by default.` : ""),
|
|
107
|
+
parameters: {
|
|
108
|
+
type: "object",
|
|
109
|
+
properties: {
|
|
110
|
+
query: {
|
|
111
|
+
type: "string",
|
|
112
|
+
description: "Natural language search query.",
|
|
113
|
+
},
|
|
114
|
+
category: {
|
|
115
|
+
type: "string",
|
|
116
|
+
description: "Filter by category.",
|
|
117
|
+
},
|
|
118
|
+
project: {
|
|
119
|
+
type: "string",
|
|
120
|
+
description: "Filter by project slug.",
|
|
121
|
+
},
|
|
122
|
+
limit: {
|
|
123
|
+
type: "number",
|
|
124
|
+
description: "Maximum results. Default 10.",
|
|
125
|
+
},
|
|
126
|
+
threshold: {
|
|
127
|
+
type: "number",
|
|
128
|
+
description: "Minimum similarity threshold (0-1). Default 0.3.",
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
required: ["query"],
|
|
132
|
+
},
|
|
133
|
+
execute: async (
|
|
134
|
+
_id,
|
|
135
|
+
args: {
|
|
136
|
+
query: string;
|
|
137
|
+
category?: string;
|
|
138
|
+
project?: string;
|
|
139
|
+
limit?: number;
|
|
140
|
+
threshold?: number;
|
|
141
|
+
},
|
|
142
|
+
) => {
|
|
143
|
+
try {
|
|
144
|
+
const project = args.project ?? defaultProject;
|
|
145
|
+
const result = await client.searchPatterns(
|
|
146
|
+
args.query,
|
|
147
|
+
args.category,
|
|
148
|
+
project,
|
|
149
|
+
args.limit,
|
|
150
|
+
args.threshold,
|
|
151
|
+
);
|
|
152
|
+
return {
|
|
153
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
154
|
+
details: { result },
|
|
155
|
+
};
|
|
156
|
+
} catch (err) {
|
|
157
|
+
return {
|
|
158
|
+
content: [{ type: "text", text: `Failed to search patterns: ${String(err)}` }],
|
|
159
|
+
details: { error: String(err) },
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
}),
|
|
164
|
+
{ name: "pattern_search" },
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// --------------------------------------------------------------------------
|
|
169
|
+
// 27. pattern_adopt
|
|
170
|
+
// --------------------------------------------------------------------------
|
|
171
|
+
if (isToolEnabled("pattern_adopt")) {
|
|
172
|
+
api.registerTool((ctx) => ({
|
|
173
|
+
|
|
174
|
+
name: "pattern_adopt",
|
|
175
|
+
description: "Adopt an existing pattern for use in a project. Creates a link between the pattern and the project.",
|
|
176
|
+
parameters: {
|
|
177
|
+
type: "object",
|
|
178
|
+
properties: {
|
|
179
|
+
id: {
|
|
180
|
+
type: "string",
|
|
181
|
+
description: "Pattern ID to adopt.",
|
|
182
|
+
},
|
|
183
|
+
project: {
|
|
184
|
+
type: "string",
|
|
185
|
+
description: "Project slug adopting the pattern.",
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
required: ["id", "project"],
|
|
189
|
+
},
|
|
190
|
+
execute: async (_id, args: { id: string; project: string }) => {
|
|
191
|
+
try {
|
|
192
|
+
const result = await client.adoptPattern(args.id, args.project);
|
|
193
|
+
return {
|
|
194
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
195
|
+
details: { result },
|
|
196
|
+
};
|
|
197
|
+
} catch (err) {
|
|
198
|
+
return {
|
|
199
|
+
content: [{ type: "text", text: `Failed to adopt pattern: ${String(err)}` }],
|
|
200
|
+
details: { error: String(err) },
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
}),
|
|
205
|
+
{ name: "pattern_adopt" },
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// --------------------------------------------------------------------------
|
|
210
|
+
// 28. pattern_suggest
|
|
211
|
+
// --------------------------------------------------------------------------
|
|
212
|
+
if (isToolEnabled("pattern_suggest")) {
|
|
213
|
+
api.registerTool((ctx) => ({
|
|
214
|
+
|
|
215
|
+
name: "pattern_suggest",
|
|
216
|
+
description:
|
|
217
|
+
"Get pattern suggestions for a project based on its stack and existing patterns from related projects.",
|
|
218
|
+
parameters: {
|
|
219
|
+
type: "object",
|
|
220
|
+
properties: {
|
|
221
|
+
project: {
|
|
222
|
+
type: "string",
|
|
223
|
+
description: "Project slug to get suggestions for.",
|
|
224
|
+
},
|
|
225
|
+
limit: {
|
|
226
|
+
type: "number",
|
|
227
|
+
description: "Maximum suggestions. Default 10.",
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
required: ["project"],
|
|
231
|
+
},
|
|
232
|
+
execute: async (_id, args: { project: string; limit?: number }) => {
|
|
233
|
+
try {
|
|
234
|
+
const result = await client.suggestPatterns(args.project, args.limit);
|
|
235
|
+
return {
|
|
236
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
237
|
+
details: { result },
|
|
238
|
+
};
|
|
239
|
+
} catch (err) {
|
|
240
|
+
return {
|
|
241
|
+
content: [{ type: "text", text: `Failed to suggest patterns: ${String(err)}` }],
|
|
242
|
+
details: { error: String(err) },
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
}),
|
|
247
|
+
{ name: "pattern_suggest" },
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
import type { PluginConfig } from "../pipelines/types.js";
|
|
3
|
+
import type { MemoryRelayClient } from "../client/memoryrelay-client.js";
|
|
4
|
+
|
|
5
|
+
export function registerProjectTools(
|
|
6
|
+
api: OpenClawPluginApi,
|
|
7
|
+
config: PluginConfig,
|
|
8
|
+
client: MemoryRelayClient,
|
|
9
|
+
isToolEnabled: (name: string) => boolean,
|
|
10
|
+
): void {
|
|
11
|
+
|
|
12
|
+
// --------------------------------------------------------------------------
|
|
13
|
+
// 29. project_register
|
|
14
|
+
// --------------------------------------------------------------------------
|
|
15
|
+
if (isToolEnabled("project_register")) {
|
|
16
|
+
api.registerTool((ctx) => ({
|
|
17
|
+
|
|
18
|
+
name: "project_register",
|
|
19
|
+
description: "Register a new project in MemoryRelay. Projects organize memories, decisions, patterns, and sessions.",
|
|
20
|
+
parameters: {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
slug: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "URL-friendly project identifier (e.g., 'my-api', 'frontend-app').",
|
|
26
|
+
},
|
|
27
|
+
name: {
|
|
28
|
+
type: "string",
|
|
29
|
+
description: "Human-readable project name.",
|
|
30
|
+
},
|
|
31
|
+
description: {
|
|
32
|
+
type: "string",
|
|
33
|
+
description: "Project description.",
|
|
34
|
+
},
|
|
35
|
+
stack: {
|
|
36
|
+
type: "object",
|
|
37
|
+
description: "Technology stack details (e.g., {language: 'python', framework: 'fastapi'}).",
|
|
38
|
+
},
|
|
39
|
+
repo_url: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "Repository URL.",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
required: ["slug", "name"],
|
|
45
|
+
},
|
|
46
|
+
execute: async (
|
|
47
|
+
_id,
|
|
48
|
+
args: {
|
|
49
|
+
slug: string;
|
|
50
|
+
name: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
stack?: Record<string, unknown>;
|
|
53
|
+
repo_url?: string;
|
|
54
|
+
},
|
|
55
|
+
) => {
|
|
56
|
+
try {
|
|
57
|
+
const result = await client.registerProject(
|
|
58
|
+
args.slug,
|
|
59
|
+
args.name,
|
|
60
|
+
args.description,
|
|
61
|
+
args.stack,
|
|
62
|
+
args.repo_url,
|
|
63
|
+
);
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
66
|
+
details: { result },
|
|
67
|
+
};
|
|
68
|
+
} catch (err) {
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: "text", text: `Failed to register project: ${String(err)}` }],
|
|
71
|
+
details: { error: String(err) },
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
{ name: "project_register" },
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// --------------------------------------------------------------------------
|
|
81
|
+
// 30. project_list
|
|
82
|
+
// --------------------------------------------------------------------------
|
|
83
|
+
if (isToolEnabled("project_list")) {
|
|
84
|
+
api.registerTool((ctx) => ({
|
|
85
|
+
|
|
86
|
+
name: "project_list",
|
|
87
|
+
description: "List all registered projects.",
|
|
88
|
+
parameters: {
|
|
89
|
+
type: "object",
|
|
90
|
+
properties: {
|
|
91
|
+
limit: {
|
|
92
|
+
type: "number",
|
|
93
|
+
description: "Maximum projects to return. Default 20.",
|
|
94
|
+
minimum: 1,
|
|
95
|
+
maximum: 100,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
execute: async (_id, args: { limit?: number }) => {
|
|
100
|
+
try {
|
|
101
|
+
const result = await client.listProjects(args.limit);
|
|
102
|
+
return {
|
|
103
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
104
|
+
details: { result },
|
|
105
|
+
};
|
|
106
|
+
} catch (err) {
|
|
107
|
+
return {
|
|
108
|
+
content: [{ type: "text", text: `Failed to list projects: ${String(err)}` }],
|
|
109
|
+
details: { error: String(err) },
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
}),
|
|
114
|
+
{ name: "project_list" },
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// --------------------------------------------------------------------------
|
|
119
|
+
// 31. project_info
|
|
120
|
+
// --------------------------------------------------------------------------
|
|
121
|
+
if (isToolEnabled("project_info")) {
|
|
122
|
+
api.registerTool((ctx) => ({
|
|
123
|
+
|
|
124
|
+
name: "project_info",
|
|
125
|
+
description: "Get detailed information about a specific project.",
|
|
126
|
+
parameters: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
slug: {
|
|
130
|
+
type: "string",
|
|
131
|
+
description: "Project slug.",
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
required: ["slug"],
|
|
135
|
+
},
|
|
136
|
+
execute: async (_id, args: { slug: string }) => {
|
|
137
|
+
try {
|
|
138
|
+
const result = await client.getProject(args.slug);
|
|
139
|
+
return {
|
|
140
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
141
|
+
details: { result },
|
|
142
|
+
};
|
|
143
|
+
} catch (err) {
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: "text", text: `Failed to get project: ${String(err)}` }],
|
|
146
|
+
details: { error: String(err) },
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
}),
|
|
151
|
+
{ name: "project_info" },
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// --------------------------------------------------------------------------
|
|
156
|
+
// 32. project_add_relationship
|
|
157
|
+
// --------------------------------------------------------------------------
|
|
158
|
+
if (isToolEnabled("project_add_relationship")) {
|
|
159
|
+
api.registerTool((ctx) => ({
|
|
160
|
+
|
|
161
|
+
name: "project_add_relationship",
|
|
162
|
+
description:
|
|
163
|
+
"Add a relationship between two projects (e.g., depends_on, api_consumer, shares_schema, shares_infra, pattern_source, forked_from).",
|
|
164
|
+
parameters: {
|
|
165
|
+
type: "object",
|
|
166
|
+
properties: {
|
|
167
|
+
from: {
|
|
168
|
+
type: "string",
|
|
169
|
+
description: "Source project slug.",
|
|
170
|
+
},
|
|
171
|
+
to: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "Target project slug.",
|
|
174
|
+
},
|
|
175
|
+
type: {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "Relationship type (e.g., depends_on, api_consumer, shares_schema, shares_infra, pattern_source, forked_from).",
|
|
178
|
+
},
|
|
179
|
+
metadata: {
|
|
180
|
+
type: "object",
|
|
181
|
+
description: "Optional metadata about the relationship.",
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
required: ["from", "to", "type"],
|
|
185
|
+
},
|
|
186
|
+
execute: async (
|
|
187
|
+
_id,
|
|
188
|
+
args: { from: string; to: string; type: string; metadata?: Record<string, unknown> },
|
|
189
|
+
) => {
|
|
190
|
+
try {
|
|
191
|
+
const result = await client.addProjectRelationship(
|
|
192
|
+
args.from,
|
|
193
|
+
args.to,
|
|
194
|
+
args.type,
|
|
195
|
+
args.metadata,
|
|
196
|
+
);
|
|
197
|
+
return {
|
|
198
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
199
|
+
details: { result },
|
|
200
|
+
};
|
|
201
|
+
} catch (err) {
|
|
202
|
+
return {
|
|
203
|
+
content: [{ type: "text", text: `Failed to add relationship: ${String(err)}` }],
|
|
204
|
+
details: { error: String(err) },
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
}),
|
|
209
|
+
{ name: "project_add_relationship" },
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// --------------------------------------------------------------------------
|
|
214
|
+
// 33. project_dependencies
|
|
215
|
+
// --------------------------------------------------------------------------
|
|
216
|
+
if (isToolEnabled("project_dependencies")) {
|
|
217
|
+
api.registerTool((ctx) => ({
|
|
218
|
+
|
|
219
|
+
name: "project_dependencies",
|
|
220
|
+
description: "List projects that a given project depends on.",
|
|
221
|
+
parameters: {
|
|
222
|
+
type: "object",
|
|
223
|
+
properties: {
|
|
224
|
+
project: {
|
|
225
|
+
type: "string",
|
|
226
|
+
description: "Project slug.",
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
required: ["project"],
|
|
230
|
+
},
|
|
231
|
+
execute: async (_id, args: { project: string }) => {
|
|
232
|
+
try {
|
|
233
|
+
const result = await client.getProjectDependencies(args.project);
|
|
234
|
+
return {
|
|
235
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
236
|
+
details: { result },
|
|
237
|
+
};
|
|
238
|
+
} catch (err) {
|
|
239
|
+
return {
|
|
240
|
+
content: [{ type: "text", text: `Failed to get dependencies: ${String(err)}` }],
|
|
241
|
+
details: { error: String(err) },
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
}),
|
|
246
|
+
{ name: "project_dependencies" },
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// --------------------------------------------------------------------------
|
|
251
|
+
// 34. project_dependents
|
|
252
|
+
// --------------------------------------------------------------------------
|
|
253
|
+
if (isToolEnabled("project_dependents")) {
|
|
254
|
+
api.registerTool((ctx) => ({
|
|
255
|
+
|
|
256
|
+
name: "project_dependents",
|
|
257
|
+
description: "List projects that depend on a given project.",
|
|
258
|
+
parameters: {
|
|
259
|
+
type: "object",
|
|
260
|
+
properties: {
|
|
261
|
+
project: {
|
|
262
|
+
type: "string",
|
|
263
|
+
description: "Project slug.",
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
required: ["project"],
|
|
267
|
+
},
|
|
268
|
+
execute: async (_id, args: { project: string }) => {
|
|
269
|
+
try {
|
|
270
|
+
const result = await client.getProjectDependents(args.project);
|
|
271
|
+
return {
|
|
272
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
273
|
+
details: { result },
|
|
274
|
+
};
|
|
275
|
+
} catch (err) {
|
|
276
|
+
return {
|
|
277
|
+
content: [{ type: "text", text: `Failed to get dependents: ${String(err)}` }],
|
|
278
|
+
details: { error: String(err) },
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
|
+
{ name: "project_dependents" },
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// --------------------------------------------------------------------------
|
|
288
|
+
// 35. project_related
|
|
289
|
+
// --------------------------------------------------------------------------
|
|
290
|
+
if (isToolEnabled("project_related")) {
|
|
291
|
+
api.registerTool((ctx) => ({
|
|
292
|
+
|
|
293
|
+
name: "project_related",
|
|
294
|
+
description: "List all projects related to a given project (any relationship direction).",
|
|
295
|
+
parameters: {
|
|
296
|
+
type: "object",
|
|
297
|
+
properties: {
|
|
298
|
+
project: {
|
|
299
|
+
type: "string",
|
|
300
|
+
description: "Project slug.",
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
required: ["project"],
|
|
304
|
+
},
|
|
305
|
+
execute: async (_id, args: { project: string }) => {
|
|
306
|
+
try {
|
|
307
|
+
const result = await client.getProjectRelated(args.project);
|
|
308
|
+
return {
|
|
309
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
310
|
+
details: { result },
|
|
311
|
+
};
|
|
312
|
+
} catch (err) {
|
|
313
|
+
return {
|
|
314
|
+
content: [{ type: "text", text: `Failed to get related projects: ${String(err)}` }],
|
|
315
|
+
details: { error: String(err) },
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
}),
|
|
320
|
+
{ name: "project_related" },
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// --------------------------------------------------------------------------
|
|
325
|
+
// 36. project_impact
|
|
326
|
+
// --------------------------------------------------------------------------
|
|
327
|
+
if (isToolEnabled("project_impact")) {
|
|
328
|
+
api.registerTool((ctx) => ({
|
|
329
|
+
|
|
330
|
+
name: "project_impact",
|
|
331
|
+
description:
|
|
332
|
+
"Analyze the impact of a proposed change on a project and its dependents. Helps understand blast radius before making changes.",
|
|
333
|
+
parameters: {
|
|
334
|
+
type: "object",
|
|
335
|
+
properties: {
|
|
336
|
+
project: {
|
|
337
|
+
type: "string",
|
|
338
|
+
description: "Project slug to analyze.",
|
|
339
|
+
},
|
|
340
|
+
change_description: {
|
|
341
|
+
type: "string",
|
|
342
|
+
description: "Description of the proposed change.",
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
required: ["project", "change_description"],
|
|
346
|
+
},
|
|
347
|
+
execute: async (_id, args: { project: string; change_description: string }) => {
|
|
348
|
+
try {
|
|
349
|
+
const result = await client.projectImpact(args.project, args.change_description);
|
|
350
|
+
return {
|
|
351
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
352
|
+
details: { result },
|
|
353
|
+
};
|
|
354
|
+
} catch (err) {
|
|
355
|
+
return {
|
|
356
|
+
content: [{ type: "text", text: `Failed to analyze impact: ${String(err)}` }],
|
|
357
|
+
details: { error: String(err) },
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
}),
|
|
362
|
+
{ name: "project_impact" },
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// --------------------------------------------------------------------------
|
|
367
|
+
// 37. project_shared_patterns
|
|
368
|
+
// --------------------------------------------------------------------------
|
|
369
|
+
if (isToolEnabled("project_shared_patterns")) {
|
|
370
|
+
api.registerTool((ctx) => ({
|
|
371
|
+
|
|
372
|
+
name: "project_shared_patterns",
|
|
373
|
+
description: "Find patterns shared between two projects. Useful for maintaining consistency across related projects.",
|
|
374
|
+
parameters: {
|
|
375
|
+
type: "object",
|
|
376
|
+
properties: {
|
|
377
|
+
project_a: {
|
|
378
|
+
type: "string",
|
|
379
|
+
description: "First project slug.",
|
|
380
|
+
},
|
|
381
|
+
project_b: {
|
|
382
|
+
type: "string",
|
|
383
|
+
description: "Second project slug.",
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
required: ["project_a", "project_b"],
|
|
387
|
+
},
|
|
388
|
+
execute: async (_id, args: { project_a: string; project_b: string }) => {
|
|
389
|
+
try {
|
|
390
|
+
const result = await client.getSharedPatterns(args.project_a, args.project_b);
|
|
391
|
+
return {
|
|
392
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
393
|
+
details: { result },
|
|
394
|
+
};
|
|
395
|
+
} catch (err) {
|
|
396
|
+
return {
|
|
397
|
+
content: [{ type: "text", text: `Failed to get shared patterns: ${String(err)}` }],
|
|
398
|
+
details: { error: String(err) },
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
}),
|
|
403
|
+
{ name: "project_shared_patterns" },
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// --------------------------------------------------------------------------
|
|
408
|
+
// 38. project_context
|
|
409
|
+
// --------------------------------------------------------------------------
|
|
410
|
+
if (isToolEnabled("project_context")) {
|
|
411
|
+
api.registerTool((ctx) => ({
|
|
412
|
+
|
|
413
|
+
name: "project_context",
|
|
414
|
+
description:
|
|
415
|
+
"Load full project context including hot-tier memories, active decisions, adopted patterns, and recent sessions. Call this FIRST when starting work on a project to understand existing context before making changes.",
|
|
416
|
+
parameters: {
|
|
417
|
+
type: "object",
|
|
418
|
+
properties: {
|
|
419
|
+
project: {
|
|
420
|
+
type: "string",
|
|
421
|
+
description: "Project slug.",
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
required: ["project"],
|
|
425
|
+
},
|
|
426
|
+
execute: async (_id, args: { project: string }) => {
|
|
427
|
+
try {
|
|
428
|
+
const result = await client.getProjectContext(args.project);
|
|
429
|
+
return {
|
|
430
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
431
|
+
details: { result },
|
|
432
|
+
};
|
|
433
|
+
} catch (err) {
|
|
434
|
+
return {
|
|
435
|
+
content: [{ type: "text", text: `Failed to load project context: ${String(err)}` }],
|
|
436
|
+
details: { error: String(err) },
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
}),
|
|
441
|
+
{ name: "project_context" },
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
}
|