@hdwebsoft/hdcode-agent-team 0.2.1 → 0.2.2
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/index.js +86 -71
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -236,36 +236,38 @@ function createTeamTools(directory) {
|
|
|
236
236
|
description: tool.schema.string().describe("Team description")
|
|
237
237
|
},
|
|
238
238
|
async execute(args) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
239
|
+
return withTeamLock(directory, args.teamName, async () => {
|
|
240
|
+
const dir = teamDir(directory, args.teamName);
|
|
241
|
+
if (await exists(join4(dir, "config.json"))) {
|
|
242
|
+
return `Error: Team "${args.teamName}" already exists`;
|
|
243
|
+
}
|
|
244
|
+
await ensureDir(join4(dir, "tasks"));
|
|
245
|
+
await ensureDir(join4(dir, "inboxes"));
|
|
246
|
+
await ensureDir(join4(dir, "reports"));
|
|
247
|
+
const now = Date.now();
|
|
248
|
+
const leadId = `team-lead@${args.teamName}`;
|
|
249
|
+
const config = {
|
|
250
|
+
name: args.teamName,
|
|
251
|
+
description: args.description,
|
|
252
|
+
createdAt: now,
|
|
253
|
+
leadAgentId: leadId,
|
|
254
|
+
members: [
|
|
255
|
+
{
|
|
256
|
+
agentId: leadId,
|
|
257
|
+
name: "team-lead",
|
|
258
|
+
agentType: "team-lead",
|
|
259
|
+
model: "unknown",
|
|
260
|
+
planModeRequired: false,
|
|
261
|
+
joinedAt: now,
|
|
262
|
+
cwd: directory,
|
|
263
|
+
isActive: true
|
|
264
|
+
}
|
|
265
|
+
]
|
|
266
|
+
};
|
|
267
|
+
await writeJsonAtomic(join4(dir, "config.json"), config);
|
|
268
|
+
await writeJsonAtomic(join4(dir, "inboxes", "team-lead.json"), []);
|
|
269
|
+
return JSON.stringify(config, null, 2);
|
|
270
|
+
});
|
|
269
271
|
}
|
|
270
272
|
}),
|
|
271
273
|
team_delete: tool({
|
|
@@ -274,12 +276,14 @@ function createTeamTools(directory) {
|
|
|
274
276
|
teamName: tool.schema.string().describe("Team name to delete")
|
|
275
277
|
},
|
|
276
278
|
async execute(args) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
279
|
+
return withTeamLock(directory, args.teamName, async () => {
|
|
280
|
+
const dir = teamDir(directory, args.teamName);
|
|
281
|
+
if (!await exists(join4(dir, "config.json"))) {
|
|
282
|
+
return `Error: Team "${args.teamName}" not found`;
|
|
283
|
+
}
|
|
284
|
+
await rm2(dir, { recursive: true, force: true });
|
|
285
|
+
return `Team "${args.teamName}" deleted successfully`;
|
|
286
|
+
});
|
|
283
287
|
}
|
|
284
288
|
}),
|
|
285
289
|
team_status: tool({
|
|
@@ -791,6 +795,24 @@ function createTaskTools(directory) {
|
|
|
791
795
|
return `Error: Task "${args.taskId}" not found in team "${args.teamName}"`;
|
|
792
796
|
}
|
|
793
797
|
const task = await readJson(tPath);
|
|
798
|
+
const originalOwner = task.owner;
|
|
799
|
+
if (args.subject !== undefined)
|
|
800
|
+
task.subject = args.subject;
|
|
801
|
+
if (args.description !== undefined)
|
|
802
|
+
task.description = args.description;
|
|
803
|
+
if (args.activeForm !== undefined)
|
|
804
|
+
task.activeForm = args.activeForm;
|
|
805
|
+
if (args.owner !== undefined)
|
|
806
|
+
task.owner = args.owner;
|
|
807
|
+
if (args.metadata) {
|
|
808
|
+
let newMeta;
|
|
809
|
+
try {
|
|
810
|
+
newMeta = JSON.parse(args.metadata);
|
|
811
|
+
} catch {
|
|
812
|
+
return "Error: Invalid metadata JSON";
|
|
813
|
+
}
|
|
814
|
+
task.metadata = { ...task.metadata, ...newMeta };
|
|
815
|
+
}
|
|
794
816
|
if (args.status) {
|
|
795
817
|
const validTransitions = {
|
|
796
818
|
pending: ["in_progress"],
|
|
@@ -819,7 +841,7 @@ function createTaskTools(directory) {
|
|
|
819
841
|
if (args.status === "in_progress") {
|
|
820
842
|
const fileScope = task.metadata?.fileScope;
|
|
821
843
|
if (fileScope) {
|
|
822
|
-
const agentId =
|
|
844
|
+
const agentId = task.owner || "unknown";
|
|
823
845
|
const reserveResult = await reserveFiles(directory, args.teamName, {
|
|
824
846
|
agentId,
|
|
825
847
|
taskId: task.id,
|
|
@@ -832,36 +854,22 @@ function createTaskTools(directory) {
|
|
|
832
854
|
}
|
|
833
855
|
}
|
|
834
856
|
if (args.status === "completed") {
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
await releaseByTask(directory, args.teamName, agentId, task.id);
|
|
857
|
+
if (originalOwner) {
|
|
858
|
+
await releaseByTask(directory, args.teamName, originalOwner, task.id);
|
|
838
859
|
}
|
|
839
860
|
}
|
|
840
861
|
task.status = args.status;
|
|
841
862
|
}
|
|
842
|
-
if (args.subject !== undefined)
|
|
843
|
-
task.subject = args.subject;
|
|
844
|
-
if (args.description !== undefined)
|
|
845
|
-
task.description = args.description;
|
|
846
|
-
if (args.activeForm !== undefined)
|
|
847
|
-
task.activeForm = args.activeForm;
|
|
848
|
-
if (args.owner !== undefined)
|
|
849
|
-
task.owner = args.owner;
|
|
850
|
-
if (args.metadata) {
|
|
851
|
-
let newMeta;
|
|
852
|
-
try {
|
|
853
|
-
newMeta = JSON.parse(args.metadata);
|
|
854
|
-
} catch {
|
|
855
|
-
return "Error: Invalid metadata JSON";
|
|
856
|
-
}
|
|
857
|
-
task.metadata = { ...task.metadata, ...newMeta };
|
|
858
|
-
}
|
|
859
863
|
if (args.addBlocks) {
|
|
860
864
|
const result = parseStringArray(args.addBlocks, "addBlocks");
|
|
861
865
|
if (typeof result === "string")
|
|
862
866
|
return result;
|
|
863
867
|
const allTasks = await loadAllTasks(directory, args.teamName);
|
|
864
868
|
const taskMap = new Map(allTasks.map((t) => [t.id, t]));
|
|
869
|
+
for (const targetId of result) {
|
|
870
|
+
if (!taskMap.has(targetId))
|
|
871
|
+
return `Error: Task "${targetId}" not found — cannot add to blocks`;
|
|
872
|
+
}
|
|
865
873
|
if (hasCycleViaBlocks(task.id, result, task.blockedBy, taskMap)) {
|
|
866
874
|
return `Error: Circular dependency detected — cannot add blocks`;
|
|
867
875
|
}
|
|
@@ -870,12 +878,10 @@ function createTaskTools(directory) {
|
|
|
870
878
|
task.blocks.push(targetId);
|
|
871
879
|
}
|
|
872
880
|
const targetPath = taskFilePath(directory, args.teamName, targetId);
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
await writeJsonAtomic(targetPath, target);
|
|
878
|
-
}
|
|
881
|
+
const target = await readJson(targetPath);
|
|
882
|
+
if (!target.blockedBy.includes(task.id)) {
|
|
883
|
+
target.blockedBy.push(task.id);
|
|
884
|
+
await writeJsonAtomic(targetPath, target);
|
|
879
885
|
}
|
|
880
886
|
}
|
|
881
887
|
}
|
|
@@ -885,6 +891,10 @@ function createTaskTools(directory) {
|
|
|
885
891
|
return result;
|
|
886
892
|
const allTasks = await loadAllTasks(directory, args.teamName);
|
|
887
893
|
const taskMap = new Map(allTasks.map((t) => [t.id, t]));
|
|
894
|
+
for (const targetId of result) {
|
|
895
|
+
if (!taskMap.has(targetId))
|
|
896
|
+
return `Error: Task "${targetId}" not found — cannot add to blockedBy`;
|
|
897
|
+
}
|
|
888
898
|
if (hasCycle(task.id, result, taskMap)) {
|
|
889
899
|
return `Error: Circular dependency detected — cannot add blockedBy`;
|
|
890
900
|
}
|
|
@@ -893,12 +903,10 @@ function createTaskTools(directory) {
|
|
|
893
903
|
task.blockedBy.push(targetId);
|
|
894
904
|
}
|
|
895
905
|
const targetPath = taskFilePath(directory, args.teamName, targetId);
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
await writeJsonAtomic(targetPath, target);
|
|
901
|
-
}
|
|
906
|
+
const target = await readJson(targetPath);
|
|
907
|
+
if (!target.blocks.includes(task.id)) {
|
|
908
|
+
target.blocks.push(task.id);
|
|
909
|
+
await writeJsonAtomic(targetPath, target);
|
|
902
910
|
}
|
|
903
911
|
}
|
|
904
912
|
}
|
|
@@ -1015,6 +1023,7 @@ function createMessageTools(directory) {
|
|
|
1015
1023
|
const inboxesDir = join7(dir, "inboxes");
|
|
1016
1024
|
await ensureDir(inboxesDir);
|
|
1017
1025
|
const message = {
|
|
1026
|
+
type: args.type,
|
|
1018
1027
|
from: sender,
|
|
1019
1028
|
text: args.content,
|
|
1020
1029
|
...args.summary && { summary: args.summary },
|
|
@@ -1061,11 +1070,17 @@ function createMessageTools(directory) {
|
|
|
1061
1070
|
},
|
|
1062
1071
|
async execute(args) {
|
|
1063
1072
|
const dir = teamDir(directory, args.teamName);
|
|
1064
|
-
|
|
1073
|
+
const configPath = join7(dir, "config.json");
|
|
1074
|
+
if (!await exists(configPath)) {
|
|
1065
1075
|
return `Error: Team "${args.teamName}" not found`;
|
|
1066
1076
|
}
|
|
1067
1077
|
const agentName = args.agent.includes("@") ? args.agent.split("@")[0] : args.agent;
|
|
1068
|
-
const
|
|
1078
|
+
const config = await readJson(configPath);
|
|
1079
|
+
const member = config.members.find((m) => m.name === agentName || m.agentId === args.agent);
|
|
1080
|
+
if (!member) {
|
|
1081
|
+
return `Error: Agent "${args.agent}" not found in team "${args.teamName}"`;
|
|
1082
|
+
}
|
|
1083
|
+
const inboxPath = join7(dir, "inboxes", `${member.name}.json`);
|
|
1069
1084
|
if (args.markRead) {
|
|
1070
1085
|
return withTeamLock(directory, args.teamName, async () => {
|
|
1071
1086
|
const allMessages = await readInbox(inboxPath);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hdwebsoft/hdcode-agent-team",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "OpenCode plugin for multi-agent team coordination — per-agent inboxes, task management with dependency tracking, file reservation/locking, and atomic mkdir-based concurrency control.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|