wolfpack-mcp 1.0.79 → 1.0.81
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/dist/agentBuilderTools.js +12 -5
- package/dist/agentMemoryTools.test.js +19 -0
- package/dist/agentSelfTools.js +6 -0
- package/dist/client.js +22 -2
- package/dist/index.js +151 -1
- package/package.json +1 -1
|
@@ -116,7 +116,8 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
116
116
|
description: 'Create an alias of an agent, so the same definition can run work in parallel. ' +
|
|
117
117
|
'An agent runs one session at a time, so N concurrent workers means N aliases. ' +
|
|
118
118
|
'The alias live-tracks the source for container image, prompts, instructions, LLM, tools, skills and tasks — edit those once on the source. ' +
|
|
119
|
-
'It does NOT inherit project assignment, API key permissions
|
|
119
|
+
'It does NOT inherit project assignment, API key permissions or schedules: set those on the alias afterwards, or it will start with a read-only key and no repository. ' +
|
|
120
|
+
'Secrets are inherited only when marked shared_with_aliases on the source (same-org only); an alias-local secret of the same name overrides. ' +
|
|
120
121
|
'Aliases are auto-named from the source (e.g. "Coder (2)"). You cannot alias an alias.',
|
|
121
122
|
inputSchema: {
|
|
122
123
|
type: 'object',
|
|
@@ -714,16 +715,21 @@ export const AGENT_BUILDER_TOOLS = [
|
|
|
714
715
|
{
|
|
715
716
|
name: 'set_agent_secret',
|
|
716
717
|
description: 'Create or update a secret for an agent. ' +
|
|
717
|
-
'Name must be uppercase letters, digits, and underscores (e.g. MY_API_KEY).'
|
|
718
|
+
'Name must be uppercase letters, digits, and underscores (e.g. MY_API_KEY). ' +
|
|
719
|
+
'Omit value to change only shared_with_aliases on an existing secret.',
|
|
718
720
|
inputSchema: {
|
|
719
721
|
type: 'object',
|
|
720
722
|
properties: {
|
|
721
723
|
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
722
724
|
name: { type: 'string', description: 'Secret name (e.g. MY_API_KEY)' },
|
|
723
725
|
value: { type: 'string', description: 'Secret value (encrypted at rest)' },
|
|
726
|
+
shared_with_aliases: {
|
|
727
|
+
type: 'boolean',
|
|
728
|
+
description: 'Share with same-org aliases of this agent (default false)',
|
|
729
|
+
},
|
|
724
730
|
...ORG_SLUG_PROP,
|
|
725
731
|
},
|
|
726
|
-
required: ['agent_id', 'name'
|
|
732
|
+
required: ['agent_id', 'name'],
|
|
727
733
|
},
|
|
728
734
|
},
|
|
729
735
|
// ─── Group 7: Discovery ───────────────────────────────────────────────────
|
|
@@ -1315,11 +1321,12 @@ export async function handleAgentBuilderTool(name, args, client) {
|
|
|
1315
1321
|
.object({
|
|
1316
1322
|
agent_id: z.string(),
|
|
1317
1323
|
name: z.string(),
|
|
1318
|
-
value: z.string(),
|
|
1324
|
+
value: z.string().optional(),
|
|
1325
|
+
shared_with_aliases: z.boolean().optional(),
|
|
1319
1326
|
org_slug: orgSlugField,
|
|
1320
1327
|
})
|
|
1321
1328
|
.parse(args);
|
|
1322
|
-
const secret = await client.setAgentSecret(parsed.agent_id, parsed.name, parsed.value, resolveOrg(parsed));
|
|
1329
|
+
const secret = await client.setAgentSecret(parsed.agent_id, parsed.name, parsed.value, parsed.shared_with_aliases, resolveOrg(parsed));
|
|
1323
1330
|
return { content: [{ type: 'text', text: `Set secret "${secret.name}"` }] };
|
|
1324
1331
|
}
|
|
1325
1332
|
// ─── Discovery ────────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { AGENT_SELF_TOOLS, AGENT_MEMORY_TOOLS } from './agentSelfTools.js';
|
|
3
|
+
const names = (tools) => tools.map((t) => t.name);
|
|
4
|
+
describe('agent self and memory tool split (#1776)', () => {
|
|
5
|
+
it('keeps the memory tools out of the self tools, so they can be withheld separately', () => {
|
|
6
|
+
expect(names(AGENT_SELF_TOOLS)).toEqual(['get_self', 'get_own_sessions']);
|
|
7
|
+
});
|
|
8
|
+
it('groups every memory tool under the separately gated set', () => {
|
|
9
|
+
expect(names(AGENT_MEMORY_TOOLS).sort()).toEqual([
|
|
10
|
+
'get_memory',
|
|
11
|
+
'list_memories',
|
|
12
|
+
'save_memory',
|
|
13
|
+
]);
|
|
14
|
+
});
|
|
15
|
+
it('never lists the same tool twice', () => {
|
|
16
|
+
const all = [...names(AGENT_SELF_TOOLS), ...names(AGENT_MEMORY_TOOLS)];
|
|
17
|
+
expect(new Set(all).size).toBe(all.length);
|
|
18
|
+
});
|
|
19
|
+
});
|
package/dist/agentSelfTools.js
CHANGED
|
@@ -23,6 +23,12 @@ export const AGENT_SELF_TOOLS = [
|
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
},
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Memory tools, gated by the `agent_memory` capability so an agent whose
|
|
29
|
+
* memory is disabled (#1776) is never offered them.
|
|
30
|
+
*/
|
|
31
|
+
export const AGENT_MEMORY_TOOLS = [
|
|
26
32
|
{
|
|
27
33
|
name: 'list_memories',
|
|
28
34
|
description: 'List all your persistent memory entries. Memory persists across sessions and is scoped to you. ' +
|
package/dist/client.js
CHANGED
|
@@ -240,6 +240,22 @@ export class WolfpackClient {
|
|
|
240
240
|
throw error;
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
|
+
// Review check methods
|
|
244
|
+
async listWorkItemChecks(filter, teamSlug) {
|
|
245
|
+
const params = new URLSearchParams();
|
|
246
|
+
if (filter.workItemId)
|
|
247
|
+
params.set('workItemId', filter.workItemId);
|
|
248
|
+
if (filter.status)
|
|
249
|
+
params.set('status', filter.status);
|
|
250
|
+
const query = params.toString();
|
|
251
|
+
return this.api.get(this.withTeamSlug(`/work-item-checks${query ? `?${query}` : ''}`, teamSlug));
|
|
252
|
+
}
|
|
253
|
+
async claimWorkItemCheck(workItemId, checkId, teamSlug) {
|
|
254
|
+
return this.api.post(this.withTeamSlug(`/work-items/${workItemId}/checks/${checkId}/claim`, teamSlug), {});
|
|
255
|
+
}
|
|
256
|
+
async completeWorkItemCheck(workItemId, checkId, data, teamSlug) {
|
|
257
|
+
return this.api.post(this.withTeamSlug(`/work-items/${workItemId}/checks/${checkId}/complete`, teamSlug), data);
|
|
258
|
+
}
|
|
243
259
|
// Radar Item (Initiative/Roadmap) methods
|
|
244
260
|
async listRadarItems(options) {
|
|
245
261
|
const params = new URLSearchParams();
|
|
@@ -762,8 +778,12 @@ export class WolfpackClient {
|
|
|
762
778
|
async listAgentSecrets(agentId, orgSlug) {
|
|
763
779
|
return this.api.get(this.withOrgSlug(`/agents/${agentId}/secrets`, orgSlug));
|
|
764
780
|
}
|
|
765
|
-
async setAgentSecret(agentId, name, value, orgSlug) {
|
|
766
|
-
return this.api.post(this.withOrgSlug(`/agents/${agentId}/secrets`, orgSlug), {
|
|
781
|
+
async setAgentSecret(agentId, name, value, sharedWithAliases, orgSlug) {
|
|
782
|
+
return this.api.post(this.withOrgSlug(`/agents/${agentId}/secrets`, orgSlug), {
|
|
783
|
+
name,
|
|
784
|
+
value,
|
|
785
|
+
sharedWithAliases,
|
|
786
|
+
});
|
|
767
787
|
}
|
|
768
788
|
// ─── Agent Builder: Skills (write) ────────────────────────────────────────
|
|
769
789
|
async createSkill(body, orgSlug) {
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { allTasksChecked, getWorkItemReminders } from './workItemReminders.js';
|
|
|
11
11
|
import { validateConfig, config } from './config.js';
|
|
12
12
|
import { AGENT_BUILDER_TOOLS, handleAgentBuilderTool } from './agentBuilderTools.js';
|
|
13
13
|
import { PROCEDURE_TOOLS, handleProcedureTool } from './procedureTools.js';
|
|
14
|
-
import { AGENT_SELF_TOOLS, handleAgentSelfTool } from './agentSelfTools.js';
|
|
14
|
+
import { AGENT_SELF_TOOLS, AGENT_MEMORY_TOOLS, handleAgentSelfTool } from './agentSelfTools.js';
|
|
15
15
|
import { resolveRadarItemId } from './resolveRadarItemId.js';
|
|
16
16
|
import { fetch as proxyFetch } from './proxyFetch.js';
|
|
17
17
|
// Get current package version
|
|
@@ -214,6 +214,28 @@ const SubmitWorkItemFormSchema = z.object({
|
|
|
214
214
|
.optional()
|
|
215
215
|
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
216
216
|
});
|
|
217
|
+
const ListWorkItemChecksSchema = z.object({
|
|
218
|
+
work_item_id: refIdString()
|
|
219
|
+
.optional()
|
|
220
|
+
.describe('The refId of a work item; omit for your reviewer inbox'),
|
|
221
|
+
status: z.enum(['pending', 'passed', 'failed']).optional().describe('Filter by check status'),
|
|
222
|
+
project_slug: z
|
|
223
|
+
.string()
|
|
224
|
+
.optional()
|
|
225
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
226
|
+
});
|
|
227
|
+
const ClaimWorkItemCheckSchema = z.object({
|
|
228
|
+
work_item_id: refIdString().describe('The refId of the work item'),
|
|
229
|
+
check_id: z.string().describe('The check ID (from list_work_item_checks)'),
|
|
230
|
+
project_slug: z
|
|
231
|
+
.string()
|
|
232
|
+
.optional()
|
|
233
|
+
.describe('Project slug (required for multi-project users, use list_projects to get slugs)'),
|
|
234
|
+
});
|
|
235
|
+
const CompleteWorkItemCheckSchema = ClaimWorkItemCheckSchema.extend({
|
|
236
|
+
status: z.enum(['passed', 'failed']).describe('The verdict'),
|
|
237
|
+
summary: z.string().optional().describe('Short summary of the review findings'),
|
|
238
|
+
});
|
|
217
239
|
// Radar Item (Initiative/Roadmap) schemas
|
|
218
240
|
const ListRadarItemsSchema = z.object({
|
|
219
241
|
project_slug: z.string().optional().describe('Project slug to filter radar items'),
|
|
@@ -641,6 +663,11 @@ const AddDiscussionCommentSchema = z.object({
|
|
|
641
663
|
const PASSTHROUGH_FIELDS = new Set(['formDefinition', 'formValues', 'formContent']);
|
|
642
664
|
// Strip UUID v4 fields from response objects so agents use refId/slug instead.
|
|
643
665
|
// Preserves Clerk user IDs (user_xxx format) and operational fields (categoryId, radarItemId).
|
|
666
|
+
/** Present a review check with its ID under `checkId` (stripUuids would drop `id`). */
|
|
667
|
+
function formatWorkItemCheck(check) {
|
|
668
|
+
const { id, workItemId: _workItemId, ...rest } = check;
|
|
669
|
+
return { checkId: id, ...rest };
|
|
670
|
+
}
|
|
644
671
|
function stripUuids(obj) {
|
|
645
672
|
if (obj === null || obj === undefined)
|
|
646
673
|
return obj;
|
|
@@ -758,6 +785,8 @@ class WolfpackMCPServer {
|
|
|
758
785
|
'AGENTS: unless granted the mcp:work_items:read_all permission, your results are always ' +
|
|
759
786
|
'narrowed to items assigned to you or routed to a work pool you belong to, whatever ' +
|
|
760
787
|
'assigned_to_id you pass; the response says so when this applies. ' +
|
|
788
|
+
'AGENTS: when more than one item is claimable, the response also states the order to take ' +
|
|
789
|
+
'them in (bug fixes first, then higher priority, then oldest) and which to pull next. ' +
|
|
761
790
|
'TERMINOLOGY: "board" and "kanban" are synonymous - both refer to the Kanban board of work items. ' +
|
|
762
791
|
'The board has columns: "new" (to do), "doing" (in progress), "review" (pending review), "ready" (code done, awaiting deployment), "blocked", "completed" (deployed). ' +
|
|
763
792
|
'The "backlog" or "pending" status represents items not yet on the board. ' +
|
|
@@ -836,6 +865,7 @@ class WolfpackMCPServer {
|
|
|
836
865
|
'blocked/ready/completed/closed→new→doing, then review when done). ' +
|
|
837
866
|
'PLANNING: Check if the description contains a plan (markdown checklist). If not, APPEND one using update_work_progress - preserve all original description text and add your plan below a "---" separator. ' +
|
|
838
867
|
'FORMS: Procedure-created work items may include formDefinition (field definitions with name, label, type, required, options) and formValues (current values). Use submit_work_item_form to fill in form values. ' +
|
|
868
|
+
'REVIEW CHECKS: items under review may carry review checks (code-review, security-review, ...); see list_work_item_checks and claim/complete_work_item_check. ' +
|
|
839
869
|
'IMAGES: Image references in the description (e.g. ``) can be viewed using the download_image tool.',
|
|
840
870
|
inputSchema: {
|
|
841
871
|
type: 'object',
|
|
@@ -986,6 +1016,8 @@ class WolfpackMCPServer {
|
|
|
986
1016
|
'agent and will return 403: ask a human to route it to your pool or assign it to you. ' +
|
|
987
1017
|
'AGENTS: pulling puts the item straight into "doing" — you are taking it to start on it ' +
|
|
988
1018
|
'now — so there is no separate "move it to doing" step. Move it to "review" when done. ' +
|
|
1019
|
+
'AGENTS: with more than one item claimable, take them in the order list_work_items gives ' +
|
|
1020
|
+
'you: bug fixes first, then higher priority, then oldest. ' +
|
|
989
1021
|
'If no assignee is specified, assigns to the API key owner. ' +
|
|
990
1022
|
'In personal projects, items are always assigned to the owner.',
|
|
991
1023
|
inputSchema: {
|
|
@@ -1031,6 +1063,79 @@ class WolfpackMCPServer {
|
|
|
1031
1063
|
required: ['work_item_id', 'form_values'],
|
|
1032
1064
|
},
|
|
1033
1065
|
},
|
|
1066
|
+
{
|
|
1067
|
+
name: 'list_work_item_checks',
|
|
1068
|
+
description: 'List review checks (key controls such as code-review, security-review, e2e-review) on work items. ' +
|
|
1069
|
+
'With work_item_id: every check on that item. Without it: your REVIEWER INBOX — pending checks on ' +
|
|
1070
|
+
'work items in the work pools you belong to that are unclaimed or held by you, each with workItemRefId and workItemTitle. ' +
|
|
1071
|
+
'REVIEW WORKFLOW: claim a check with claim_work_item_check, get_work_item to read the work, review it, ' +
|
|
1072
|
+
'then complete_work_item_check with "passed" or "failed" and a short summary. ' +
|
|
1073
|
+
'A failed check sends the item back to its developer with your summary as feedback; do not change the item status yourself.',
|
|
1074
|
+
inputSchema: {
|
|
1075
|
+
type: 'object',
|
|
1076
|
+
properties: {
|
|
1077
|
+
work_item_id: {
|
|
1078
|
+
type: 'string',
|
|
1079
|
+
description: 'The refId of a work item; omit for your reviewer inbox',
|
|
1080
|
+
},
|
|
1081
|
+
status: {
|
|
1082
|
+
type: 'string',
|
|
1083
|
+
enum: ['pending', 'passed', 'failed'],
|
|
1084
|
+
description: 'Filter by check status',
|
|
1085
|
+
},
|
|
1086
|
+
project_slug: {
|
|
1087
|
+
type: 'string',
|
|
1088
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
1089
|
+
},
|
|
1090
|
+
},
|
|
1091
|
+
},
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
name: 'claim_work_item_check',
|
|
1095
|
+
description: 'Claim a pending, unclaimed review check on a work item so other reviewers know it is being handled. ' +
|
|
1096
|
+
'Only one reviewer can hold a check; the claim is refused if someone else got there first.',
|
|
1097
|
+
inputSchema: {
|
|
1098
|
+
type: 'object',
|
|
1099
|
+
properties: {
|
|
1100
|
+
work_item_id: { type: 'string', description: 'The refId of the work item' },
|
|
1101
|
+
check_id: {
|
|
1102
|
+
type: 'string',
|
|
1103
|
+
description: 'The check ID (checkId from list_work_item_checks)',
|
|
1104
|
+
},
|
|
1105
|
+
project_slug: {
|
|
1106
|
+
type: 'string',
|
|
1107
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
1108
|
+
},
|
|
1109
|
+
},
|
|
1110
|
+
required: ['work_item_id', 'check_id'],
|
|
1111
|
+
},
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
1114
|
+
name: 'complete_work_item_check',
|
|
1115
|
+
description: 'Record the verdict on a review check: "passed" or "failed", with a short summary of the findings. ' +
|
|
1116
|
+
'A claimed check can only be completed by its claimant (or an admin). When every check on the item is ' +
|
|
1117
|
+
'resolved the owning procedure continues — with a failed check it returns the item to the developer with the summaries as feedback.',
|
|
1118
|
+
inputSchema: {
|
|
1119
|
+
type: 'object',
|
|
1120
|
+
properties: {
|
|
1121
|
+
work_item_id: { type: 'string', description: 'The refId of the work item' },
|
|
1122
|
+
check_id: {
|
|
1123
|
+
type: 'string',
|
|
1124
|
+
description: 'The check ID (checkId from list_work_item_checks)',
|
|
1125
|
+
},
|
|
1126
|
+
status: { type: 'string', enum: ['passed', 'failed'], description: 'The verdict' },
|
|
1127
|
+
summary: {
|
|
1128
|
+
type: 'string',
|
|
1129
|
+
description: 'Short summary of the review findings (what was checked, what failed)',
|
|
1130
|
+
},
|
|
1131
|
+
project_slug: {
|
|
1132
|
+
type: 'string',
|
|
1133
|
+
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
1134
|
+
},
|
|
1135
|
+
},
|
|
1136
|
+
required: ['work_item_id', 'check_id', 'status'],
|
|
1137
|
+
},
|
|
1138
|
+
},
|
|
1034
1139
|
// Radar Item (Initiative/Roadmap) tools
|
|
1035
1140
|
{
|
|
1036
1141
|
name: 'list_radar_items',
|
|
@@ -2040,6 +2145,7 @@ class WolfpackMCPServer {
|
|
|
2040
2145
|
},
|
|
2041
2146
|
...(this.capabilities.includes('procedures') ? PROCEDURE_TOOLS : []),
|
|
2042
2147
|
...(this.capabilities.includes('agent_self') ? AGENT_SELF_TOOLS : []),
|
|
2148
|
+
...(this.capabilities.includes('agent_memory') ? AGENT_MEMORY_TOOLS : []),
|
|
2043
2149
|
...(this.capabilities.includes('agent_builder') ? AGENT_BUILDER_TOOLS : []),
|
|
2044
2150
|
],
|
|
2045
2151
|
};
|
|
@@ -2309,6 +2415,43 @@ class WolfpackMCPServer {
|
|
|
2309
2415
|
content: [{ type: 'text', text: 'Work item not found' }],
|
|
2310
2416
|
};
|
|
2311
2417
|
}
|
|
2418
|
+
case 'list_work_item_checks': {
|
|
2419
|
+
const parsed = ListWorkItemChecksSchema.parse(args);
|
|
2420
|
+
const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
|
|
2421
|
+
const checks = await this.client.listWorkItemChecks({ workItemId: parsed.work_item_id, status: parsed.status }, teamSlug);
|
|
2422
|
+
const text = checks.length === 0
|
|
2423
|
+
? parsed.work_item_id
|
|
2424
|
+
? 'No review checks on this work item'
|
|
2425
|
+
: 'No review checks waiting for you'
|
|
2426
|
+
: JSON.stringify(checks.map(formatWorkItemCheck), null, 2);
|
|
2427
|
+
return { content: [{ type: 'text', text }] };
|
|
2428
|
+
}
|
|
2429
|
+
case 'claim_work_item_check': {
|
|
2430
|
+
const parsed = ClaimWorkItemCheckSchema.parse(args);
|
|
2431
|
+
const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
|
|
2432
|
+
const check = await this.client.claimWorkItemCheck(parsed.work_item_id, parsed.check_id, teamSlug);
|
|
2433
|
+
return {
|
|
2434
|
+
content: [
|
|
2435
|
+
{
|
|
2436
|
+
type: 'text',
|
|
2437
|
+
text: `Claimed ${check.kind} check on #${check.workItemRefId} "${check.workItemTitle}"\n\n${JSON.stringify(formatWorkItemCheck(check), null, 2)}`,
|
|
2438
|
+
},
|
|
2439
|
+
],
|
|
2440
|
+
};
|
|
2441
|
+
}
|
|
2442
|
+
case 'complete_work_item_check': {
|
|
2443
|
+
const parsed = CompleteWorkItemCheckSchema.parse(args);
|
|
2444
|
+
const teamSlug = parsed.project_slug || this.client.getProjectSlug() || undefined;
|
|
2445
|
+
const check = await this.client.completeWorkItemCheck(parsed.work_item_id, parsed.check_id, { status: parsed.status, summary: parsed.summary }, teamSlug);
|
|
2446
|
+
return {
|
|
2447
|
+
content: [
|
|
2448
|
+
{
|
|
2449
|
+
type: 'text',
|
|
2450
|
+
text: `Marked ${check.kind} check on #${check.workItemRefId} as ${check.status}\n\n${JSON.stringify(formatWorkItemCheck(check), null, 2)}`,
|
|
2451
|
+
},
|
|
2452
|
+
],
|
|
2453
|
+
};
|
|
2454
|
+
}
|
|
2312
2455
|
// Radar Item handlers
|
|
2313
2456
|
case 'list_radar_items': {
|
|
2314
2457
|
const parsed = ListRadarItemsSchema.parse(args);
|
|
@@ -2965,6 +3108,13 @@ class WolfpackMCPServer {
|
|
|
2965
3108
|
return handleAgentSelfTool(name, args, this.client);
|
|
2966
3109
|
}
|
|
2967
3110
|
}
|
|
3111
|
+
// Check memory tools (separately gated — #1776)
|
|
3112
|
+
if (this.capabilities.includes('agent_memory')) {
|
|
3113
|
+
const memoryToolNames = AGENT_MEMORY_TOOLS.map((t) => t.name);
|
|
3114
|
+
if (memoryToolNames.includes(name)) {
|
|
3115
|
+
return handleAgentSelfTool(name, args, this.client);
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
2968
3118
|
// Check agent builder tools
|
|
2969
3119
|
if (this.capabilities.includes('agent_builder')) {
|
|
2970
3120
|
return handleAgentBuilderTool(name, args, this.client);
|