@opengoat/core 2026.2.13 → 2026.2.14-3
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/core/agents/application/agent.service.d.ts +2 -0
- package/dist/core/agents/application/agent.service.js +67 -25
- package/dist/core/agents/application/agent.service.js.map +1 -1
- package/dist/core/bootstrap/application/bootstrap.service.d.ts +4 -0
- package/dist/core/bootstrap/application/bootstrap.service.js +28 -1
- package/dist/core/bootstrap/application/bootstrap.service.js.map +1 -1
- package/dist/core/domain/opengoat-paths.d.ts +1 -0
- package/dist/core/opengoat/application/opengoat.service.d.ts +7 -0
- package/dist/core/opengoat/application/opengoat.service.helpers.d.ts +52 -0
- package/dist/core/opengoat/application/opengoat.service.helpers.js +325 -0
- package/dist/core/opengoat/application/opengoat.service.helpers.js.map +1 -0
- package/dist/core/opengoat/application/opengoat.service.js +83 -289
- package/dist/core/opengoat/application/opengoat.service.js.map +1 -1
- package/dist/core/providers/application/provider.service.d.ts +1 -0
- package/dist/core/providers/application/provider.service.js +63 -1
- package/dist/core/providers/application/provider.service.js.map +1 -1
- package/dist/core/templates/assets/ceo/BOOTSTRAP.md +41 -0
- package/dist/core/templates/assets/ceo/ROLE.md +2 -0
- package/dist/core/templates/assets/organization/MISSION.md +73 -0
- package/dist/core/templates/assets/organization/STRATEGY.md +107 -0
- package/dist/core/templates/assets/organization/VISION.md +80 -0
- package/dist/core/templates/assets/organization/wiki/index.md +15 -0
- package/dist/core/templates/default-templates.d.ts +6 -1
- package/dist/core/templates/default-templates.js +52 -5
- package/dist/core/templates/default-templates.js.map +1 -1
- package/dist/platform/node/node-path.port.js +1 -0
- package/dist/platform/node/node-path.port.js.map +1 -1
- package/package.json +1 -1
- package/dist/core/templates/assets/ceo/AGENTS.md +0 -20
- package/dist/core/templates/assets/ceo/SOUL.md +0 -15
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
1
|
import { AgentManifestService } from "../../agents/application/agent-manifest.service.js";
|
|
4
2
|
import { AgentService } from "../../agents/application/agent.service.js";
|
|
5
3
|
import { BoardService, } from "../../boards/index.js";
|
|
@@ -11,6 +9,7 @@ import { ProviderService } from "../../providers/application/provider.service.js
|
|
|
11
9
|
import { ProviderCommandNotFoundError, createDefaultProviderRegistry, } from "../../providers/index.js";
|
|
12
10
|
import { SessionService, } from "../../sessions/index.js";
|
|
13
11
|
import { SkillService, } from "../../skills/index.js";
|
|
12
|
+
import { assertAgentExists, buildBlockedTaskMessage, buildInactiveAgentMessage, buildInactiveSessionRef, buildReporteeStats, buildTaskSessionRef, buildTodoTaskMessage, collectAllReportees, containsAgentNotFoundMessage, containsAlreadyExistsMessage, extractManagedSkillsDir, extractOpenClawAgentEntry, extractOpenClawAgents, isSpawnPermissionOrMissing, pathIsWithin, pathMatches, prepareOpenClawCommandEnv, resolveInactiveAgentNotificationTarget, resolveInactiveMinutes, toErrorMessage, } from "./opengoat.service.helpers.js";
|
|
14
13
|
const OPENCLAW_PROVIDER_ID = "openclaw";
|
|
15
14
|
const OPENCLAW_DEFAULT_AGENT_ID = "main";
|
|
16
15
|
export class OpenGoatService {
|
|
@@ -51,6 +50,7 @@ export class OpenGoatService {
|
|
|
51
50
|
});
|
|
52
51
|
this.bootstrapService = new BootstrapService({
|
|
53
52
|
fileSystem: deps.fileSystem,
|
|
53
|
+
pathPort: deps.pathPort,
|
|
54
54
|
pathsProvider: deps.pathsProvider,
|
|
55
55
|
agentService: this.agentService,
|
|
56
56
|
nowIso,
|
|
@@ -107,6 +107,7 @@ export class OpenGoatService {
|
|
|
107
107
|
}
|
|
108
108
|
candidateOpenClawAgentIds.add(agent.id);
|
|
109
109
|
}
|
|
110
|
+
await this.addWorkspaceAgentCandidates(paths, candidateOpenClawAgentIds, warnings);
|
|
110
111
|
try {
|
|
111
112
|
const openClawAgents = await this.listOpenClawAgents(paths);
|
|
112
113
|
for (const entry of openClawAgents) {
|
|
@@ -388,12 +389,13 @@ export class OpenGoatService {
|
|
|
388
389
|
this.agentService.listAgents(paths),
|
|
389
390
|
this.agentManifestService.listManifests(paths),
|
|
390
391
|
]);
|
|
392
|
+
const reporteeStats = buildReporteeStats(manifests);
|
|
391
393
|
const descriptorsById = new Map(agents.map((agent) => [agent.id, agent]));
|
|
392
394
|
const agent = descriptorsById.get(agentId);
|
|
393
395
|
if (!agent) {
|
|
394
396
|
throw new Error(`Agent "${agentId}" does not exist.`);
|
|
395
397
|
}
|
|
396
|
-
const totalReportees =
|
|
398
|
+
const totalReportees = reporteeStats.totalByManager.get(agentId) ?? 0;
|
|
397
399
|
const directReportees = manifests
|
|
398
400
|
.filter((manifest) => manifest.metadata.reportsTo === agentId)
|
|
399
401
|
.map((manifest) => {
|
|
@@ -406,8 +408,7 @@ export class OpenGoatService {
|
|
|
406
408
|
id: manifest.agentId,
|
|
407
409
|
name,
|
|
408
410
|
role,
|
|
409
|
-
totalReportees:
|
|
410
|
-
.length,
|
|
411
|
+
totalReportees: reporteeStats.totalByManager.get(manifest.agentId) ?? 0,
|
|
411
412
|
};
|
|
412
413
|
})
|
|
413
414
|
.sort((left, right) => left.id.localeCompare(right.id));
|
|
@@ -505,12 +506,37 @@ export class OpenGoatService {
|
|
|
505
506
|
const paths = this.pathsProvider.getPaths();
|
|
506
507
|
const ranAt = this.resolveNowIso();
|
|
507
508
|
const manifests = await this.agentManifestService.listManifests(paths);
|
|
508
|
-
const manifestsById = new Map(manifests.map((manifest) => [manifest.agentId, manifest]));
|
|
509
509
|
const inactiveMinutes = resolveInactiveMinutes(options.inactiveMinutes);
|
|
510
|
-
const
|
|
510
|
+
const notificationTarget = resolveInactiveAgentNotificationTarget(options.notificationTarget);
|
|
511
|
+
const notifyInactiveAgents = options.notifyInactiveAgents ?? true;
|
|
512
|
+
const inactiveCandidates = notifyInactiveAgents
|
|
513
|
+
? await this.collectInactiveAgents(paths, manifests, inactiveMinutes, notificationTarget)
|
|
514
|
+
: [];
|
|
515
|
+
const latestCeoProjectPath = notifyInactiveAgents
|
|
516
|
+
? await this.resolveLatestProjectPathForAgent(paths, DEFAULT_AGENT_ID)
|
|
517
|
+
: undefined;
|
|
511
518
|
const tasks = await this.boardService.listTasks(paths, { limit: 10_000 });
|
|
519
|
+
const taskStatusDispatch = await this.dispatchTaskStatusAutomations(paths, tasks, manifests);
|
|
520
|
+
const inactiveDispatches = await this.dispatchInactiveAgentAutomations(paths, inactiveCandidates, inactiveMinutes, latestCeoProjectPath);
|
|
521
|
+
const dispatches = [
|
|
522
|
+
...taskStatusDispatch.dispatches,
|
|
523
|
+
...inactiveDispatches,
|
|
524
|
+
];
|
|
525
|
+
const failed = dispatches.filter((entry) => !entry.ok).length;
|
|
526
|
+
return {
|
|
527
|
+
ranAt,
|
|
528
|
+
scannedTasks: tasks.length,
|
|
529
|
+
todoTasks: taskStatusDispatch.todoTasks,
|
|
530
|
+
blockedTasks: taskStatusDispatch.blockedTasks,
|
|
531
|
+
inactiveAgents: inactiveCandidates.length,
|
|
532
|
+
sent: dispatches.length - failed,
|
|
533
|
+
failed,
|
|
534
|
+
dispatches,
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
async dispatchTaskStatusAutomations(paths, tasks, manifests) {
|
|
538
|
+
const manifestsById = new Map(manifests.map((manifest) => [manifest.agentId, manifest]));
|
|
512
539
|
const dispatches = [];
|
|
513
|
-
let scannedTasks = tasks.length;
|
|
514
540
|
let todoTasks = 0;
|
|
515
541
|
let blockedTasks = 0;
|
|
516
542
|
for (const task of tasks) {
|
|
@@ -549,6 +575,14 @@ export class OpenGoatService {
|
|
|
549
575
|
error: result.error,
|
|
550
576
|
});
|
|
551
577
|
}
|
|
578
|
+
return {
|
|
579
|
+
dispatches,
|
|
580
|
+
todoTasks,
|
|
581
|
+
blockedTasks,
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
async dispatchInactiveAgentAutomations(paths, inactiveCandidates, inactiveMinutes, latestCeoProjectPath) {
|
|
585
|
+
const dispatches = [];
|
|
552
586
|
for (const candidate of inactiveCandidates) {
|
|
553
587
|
const sessionRef = buildInactiveSessionRef(candidate.managerAgentId, candidate.subjectAgentId);
|
|
554
588
|
const message = buildInactiveAgentMessage({
|
|
@@ -556,10 +590,14 @@ export class OpenGoatService {
|
|
|
556
590
|
subjectAgentId: candidate.subjectAgentId,
|
|
557
591
|
subjectName: candidate.subjectName,
|
|
558
592
|
role: candidate.role,
|
|
593
|
+
directReporteesCount: candidate.directReporteesCount,
|
|
594
|
+
indirectReporteesCount: candidate.indirectReporteesCount,
|
|
559
595
|
inactiveMinutes,
|
|
560
596
|
lastActionTimestamp: candidate.lastActionTimestamp,
|
|
561
597
|
});
|
|
562
|
-
const result = await this.dispatchAutomationMessage(paths, candidate.managerAgentId, sessionRef, message
|
|
598
|
+
const result = await this.dispatchAutomationMessage(paths, candidate.managerAgentId, sessionRef, message, {
|
|
599
|
+
cwd: latestCeoProjectPath,
|
|
600
|
+
});
|
|
563
601
|
dispatches.push({
|
|
564
602
|
kind: "inactive",
|
|
565
603
|
targetAgentId: candidate.managerAgentId,
|
|
@@ -569,17 +607,7 @@ export class OpenGoatService {
|
|
|
569
607
|
error: result.error,
|
|
570
608
|
});
|
|
571
609
|
}
|
|
572
|
-
|
|
573
|
-
return {
|
|
574
|
-
ranAt,
|
|
575
|
-
scannedTasks,
|
|
576
|
-
todoTasks,
|
|
577
|
-
blockedTasks,
|
|
578
|
-
inactiveAgents: inactiveCandidates.length,
|
|
579
|
-
sent: dispatches.length - failed,
|
|
580
|
-
failed,
|
|
581
|
-
dispatches,
|
|
582
|
-
};
|
|
610
|
+
return dispatches;
|
|
583
611
|
}
|
|
584
612
|
async listSkills(agentId = DEFAULT_AGENT_ID) {
|
|
585
613
|
const paths = this.pathsProvider.getPaths();
|
|
@@ -673,11 +701,12 @@ export class OpenGoatService {
|
|
|
673
701
|
getPaths() {
|
|
674
702
|
return this.pathsProvider.getPaths();
|
|
675
703
|
}
|
|
676
|
-
async dispatchAutomationMessage(paths, agentId, sessionRef, message) {
|
|
704
|
+
async dispatchAutomationMessage(paths, agentId, sessionRef, message, options = {}) {
|
|
677
705
|
try {
|
|
678
706
|
const result = await this.orchestrationService.runAgent(paths, agentId, {
|
|
679
707
|
message,
|
|
680
708
|
sessionRef,
|
|
709
|
+
cwd: options.cwd,
|
|
681
710
|
env: process.env,
|
|
682
711
|
});
|
|
683
712
|
if (result.code !== 0) {
|
|
@@ -834,6 +863,21 @@ export class OpenGoatService {
|
|
|
834
863
|
}
|
|
835
864
|
return extractOpenClawAgents(parsed);
|
|
836
865
|
}
|
|
866
|
+
async addWorkspaceAgentCandidates(paths, candidates, warnings) {
|
|
867
|
+
try {
|
|
868
|
+
const workspaceDirs = await this.fileSystem.listDirectories(paths.workspacesDir);
|
|
869
|
+
for (const workspaceDir of workspaceDirs) {
|
|
870
|
+
const workspaceAgentId = normalizeAgentId(workspaceDir);
|
|
871
|
+
if (workspaceAgentId &&
|
|
872
|
+
workspaceAgentId !== OPENCLAW_DEFAULT_AGENT_ID) {
|
|
873
|
+
candidates.add(workspaceAgentId);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
catch (error) {
|
|
878
|
+
warnings.push(`Workspace fallback discovery failed: ${toErrorMessage(error)}`);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
837
881
|
async ensureOpenClawAgentLocation(paths, params) {
|
|
838
882
|
if (!this.commandRunner) {
|
|
839
883
|
return;
|
|
@@ -882,297 +926,47 @@ export class OpenGoatService {
|
|
|
882
926
|
...process.env,
|
|
883
927
|
};
|
|
884
928
|
}
|
|
885
|
-
async collectInactiveAgents(paths, manifests, inactiveMinutes) {
|
|
929
|
+
async collectInactiveAgents(paths, manifests, inactiveMinutes, notificationTarget) {
|
|
886
930
|
const nowMs = this.resolveNowMs();
|
|
887
931
|
const inactiveCutoffMs = nowMs - inactiveMinutes * 60_000;
|
|
932
|
+
const reporteeStats = buildReporteeStats(manifests);
|
|
888
933
|
const inactive = [];
|
|
889
934
|
for (const manifest of manifests) {
|
|
890
935
|
const managerAgentId = normalizeAgentId(manifest.metadata.reportsTo ?? "");
|
|
891
936
|
if (!managerAgentId) {
|
|
892
937
|
continue;
|
|
893
938
|
}
|
|
939
|
+
if (notificationTarget === "ceo-only" &&
|
|
940
|
+
managerAgentId !== DEFAULT_AGENT_ID) {
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
894
943
|
const lastAction = await this.sessionService.getLastAgentAction(paths, manifest.agentId);
|
|
895
944
|
if (lastAction && lastAction.timestamp >= inactiveCutoffMs) {
|
|
896
945
|
continue;
|
|
897
946
|
}
|
|
947
|
+
const directReporteesCount = reporteeStats.directByManager.get(manifest.agentId) ?? 0;
|
|
948
|
+
const totalReporteesCount = reporteeStats.totalByManager.get(manifest.agentId) ?? 0;
|
|
949
|
+
const indirectReporteesCount = Math.max(0, totalReporteesCount - directReporteesCount);
|
|
898
950
|
inactive.push({
|
|
899
951
|
managerAgentId,
|
|
900
952
|
subjectAgentId: manifest.agentId,
|
|
901
953
|
subjectName: manifest.metadata.name,
|
|
902
954
|
role: manifest.metadata.description,
|
|
955
|
+
directReporteesCount,
|
|
956
|
+
indirectReporteesCount,
|
|
903
957
|
lastActionTimestamp: lastAction?.timestamp,
|
|
904
958
|
});
|
|
905
959
|
}
|
|
906
960
|
return inactive;
|
|
907
961
|
}
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
}
|
|
913
|
-
function containsAgentNotFoundMessage(stdout, stderr) {
|
|
914
|
-
const text = `${stdout}\n${stderr}`.toLowerCase();
|
|
915
|
-
return /\b(not found|does not exist|no such agent|unknown agent|could not find|no agent found|not exist)\b/.test(text);
|
|
916
|
-
}
|
|
917
|
-
function toErrorMessage(error) {
|
|
918
|
-
if (error instanceof Error) {
|
|
919
|
-
return error.message;
|
|
920
|
-
}
|
|
921
|
-
return String(error);
|
|
922
|
-
}
|
|
923
|
-
function resolveInactiveMinutes(value) {
|
|
924
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
925
|
-
return 30;
|
|
926
|
-
}
|
|
927
|
-
return Math.floor(value);
|
|
928
|
-
}
|
|
929
|
-
function extractManagedSkillsDir(payload) {
|
|
930
|
-
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
931
|
-
return null;
|
|
932
|
-
}
|
|
933
|
-
const record = payload;
|
|
934
|
-
if (typeof record.managedSkillsDir !== "string") {
|
|
935
|
-
return null;
|
|
936
|
-
}
|
|
937
|
-
const managedSkillsDir = record.managedSkillsDir.trim();
|
|
938
|
-
return managedSkillsDir || null;
|
|
939
|
-
}
|
|
940
|
-
function extractOpenClawAgents(payload) {
|
|
941
|
-
if (!Array.isArray(payload)) {
|
|
942
|
-
return [];
|
|
943
|
-
}
|
|
944
|
-
const entries = [];
|
|
945
|
-
for (const entry of payload) {
|
|
946
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
947
|
-
continue;
|
|
948
|
-
}
|
|
949
|
-
const record = entry;
|
|
950
|
-
const id = normalizeAgentId(String(record.id ?? ""));
|
|
951
|
-
if (!id) {
|
|
952
|
-
continue;
|
|
953
|
-
}
|
|
954
|
-
entries.push({
|
|
955
|
-
id,
|
|
956
|
-
workspace: typeof record.workspace === "string" ? record.workspace : "",
|
|
957
|
-
agentDir: typeof record.agentDir === "string" ? record.agentDir : "",
|
|
958
|
-
});
|
|
959
|
-
}
|
|
960
|
-
return entries;
|
|
961
|
-
}
|
|
962
|
-
function extractOpenClawAgentEntry(payload, agentId) {
|
|
963
|
-
const normalizedAgentId = normalizeAgentId(agentId);
|
|
964
|
-
if (!normalizedAgentId) {
|
|
965
|
-
return null;
|
|
966
|
-
}
|
|
967
|
-
for (const entry of extractOpenClawAgents(payload)) {
|
|
968
|
-
if (entry.id !== normalizedAgentId) {
|
|
969
|
-
continue;
|
|
962
|
+
async resolveLatestProjectPathForAgent(paths, rawAgentId) {
|
|
963
|
+
const agentId = normalizeAgentId(rawAgentId);
|
|
964
|
+
if (!agentId) {
|
|
965
|
+
return undefined;
|
|
970
966
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
};
|
|
975
|
-
}
|
|
976
|
-
return null;
|
|
977
|
-
}
|
|
978
|
-
function pathMatches(left, right) {
|
|
979
|
-
const leftNormalized = normalizePathForCompare(left);
|
|
980
|
-
const rightNormalized = normalizePathForCompare(right);
|
|
981
|
-
if (!leftNormalized || !rightNormalized) {
|
|
982
|
-
return false;
|
|
983
|
-
}
|
|
984
|
-
return leftNormalized === rightNormalized;
|
|
985
|
-
}
|
|
986
|
-
function pathIsWithin(containerPath, candidatePath) {
|
|
987
|
-
const normalizedContainer = normalizePathForCompare(containerPath);
|
|
988
|
-
const normalizedCandidate = normalizePathForCompare(candidatePath);
|
|
989
|
-
if (!normalizedContainer || !normalizedCandidate) {
|
|
990
|
-
return false;
|
|
967
|
+
const sessions = await this.sessionService.listSessions(paths, agentId);
|
|
968
|
+
const latestProjectPath = sessions[0]?.projectPath?.trim();
|
|
969
|
+
return latestProjectPath || undefined;
|
|
991
970
|
}
|
|
992
|
-
const relative = path.relative(normalizedContainer, normalizedCandidate);
|
|
993
|
-
if (!relative) {
|
|
994
|
-
return true;
|
|
995
|
-
}
|
|
996
|
-
return !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
997
|
-
}
|
|
998
|
-
function normalizePathForCompare(value) {
|
|
999
|
-
const trimmed = value.trim();
|
|
1000
|
-
if (!trimmed) {
|
|
1001
|
-
return "";
|
|
1002
|
-
}
|
|
1003
|
-
const resolved = path.resolve(trimmed);
|
|
1004
|
-
if (process.platform === "win32") {
|
|
1005
|
-
return resolved.toLowerCase();
|
|
1006
|
-
}
|
|
1007
|
-
return resolved;
|
|
1008
|
-
}
|
|
1009
|
-
function buildTaskSessionRef(agentId, taskId) {
|
|
1010
|
-
const normalizedAgentId = normalizeAgentId(agentId) || DEFAULT_AGENT_ID;
|
|
1011
|
-
const normalizedTaskId = normalizeAgentId(taskId) || "task";
|
|
1012
|
-
return `agent:${normalizedAgentId}:agent_${normalizedAgentId}_task_${normalizedTaskId}`;
|
|
1013
|
-
}
|
|
1014
|
-
function buildInactiveSessionRef(managerAgentId, subjectAgentId) {
|
|
1015
|
-
const manager = normalizeAgentId(managerAgentId) || DEFAULT_AGENT_ID;
|
|
1016
|
-
const subject = normalizeAgentId(subjectAgentId) || "agent";
|
|
1017
|
-
return `agent:${manager}:agent_${manager}_inactive_${subject}`;
|
|
1018
|
-
}
|
|
1019
|
-
function buildTodoTaskMessage(params) {
|
|
1020
|
-
const blockers = params.task.blockers.length > 0 ? params.task.blockers.join("; ") : "None";
|
|
1021
|
-
const artifacts = params.task.artifacts.length > 0
|
|
1022
|
-
? params.task.artifacts
|
|
1023
|
-
.map((entry) => `- ${entry.createdAt} @${entry.createdBy}: ${entry.content}`)
|
|
1024
|
-
.join("\n")
|
|
1025
|
-
: "- None";
|
|
1026
|
-
const worklog = params.task.worklog.length > 0
|
|
1027
|
-
? params.task.worklog
|
|
1028
|
-
.map((entry) => `- ${entry.createdAt} @${entry.createdBy}: ${entry.content}`)
|
|
1029
|
-
.join("\n")
|
|
1030
|
-
: "- None";
|
|
1031
|
-
return [
|
|
1032
|
-
`Task #${params.task.taskId} is assigned to you and currently in TODO. Please work on it now.`,
|
|
1033
|
-
"",
|
|
1034
|
-
`Task ID: ${params.task.taskId}`,
|
|
1035
|
-
`Title: ${params.task.title}`,
|
|
1036
|
-
`Description: ${params.task.description}`,
|
|
1037
|
-
`Project: ${params.task.project}`,
|
|
1038
|
-
`Status: ${params.task.status}`,
|
|
1039
|
-
`Owner: @${params.task.owner}`,
|
|
1040
|
-
`Assigned to: @${params.task.assignedTo}`,
|
|
1041
|
-
`Created at: ${params.task.createdAt}`,
|
|
1042
|
-
`Blockers: ${blockers}`,
|
|
1043
|
-
"Artifacts:",
|
|
1044
|
-
artifacts,
|
|
1045
|
-
"Worklog:",
|
|
1046
|
-
worklog,
|
|
1047
|
-
].join("\n");
|
|
1048
|
-
}
|
|
1049
|
-
function buildBlockedTaskMessage(params) {
|
|
1050
|
-
const blockerReason = params.task.blockers.length > 0
|
|
1051
|
-
? params.task.blockers.join("; ")
|
|
1052
|
-
: params.task.statusReason?.trim() || "no blocker details were provided";
|
|
1053
|
-
const artifacts = params.task.artifacts.length > 0
|
|
1054
|
-
? params.task.artifacts
|
|
1055
|
-
.map((entry) => `- ${entry.createdAt} @${entry.createdBy}: ${entry.content}`)
|
|
1056
|
-
.join("\n")
|
|
1057
|
-
: "- None";
|
|
1058
|
-
const worklog = params.task.worklog.length > 0
|
|
1059
|
-
? params.task.worklog
|
|
1060
|
-
.map((entry) => `- ${entry.createdAt} @${entry.createdBy}: ${entry.content}`)
|
|
1061
|
-
.join("\n")
|
|
1062
|
-
: "- None";
|
|
1063
|
-
return [
|
|
1064
|
-
`Task #${params.task.taskId}, assigned to your reportee "@${params.task.assignedTo}" is blocked because of ${blockerReason}. Help unblocking it.`,
|
|
1065
|
-
"",
|
|
1066
|
-
`Task ID: ${params.task.taskId}`,
|
|
1067
|
-
`Title: ${params.task.title}`,
|
|
1068
|
-
`Description: ${params.task.description}`,
|
|
1069
|
-
`Project: ${params.task.project}`,
|
|
1070
|
-
`Status: ${params.task.status}`,
|
|
1071
|
-
`Owner: @${params.task.owner}`,
|
|
1072
|
-
`Assigned to: @${params.task.assignedTo}`,
|
|
1073
|
-
`Created at: ${params.task.createdAt}`,
|
|
1074
|
-
"Artifacts:",
|
|
1075
|
-
artifacts,
|
|
1076
|
-
"Worklog:",
|
|
1077
|
-
worklog,
|
|
1078
|
-
].join("\n");
|
|
1079
|
-
}
|
|
1080
|
-
function buildInactiveAgentMessage(params) {
|
|
1081
|
-
const lastAction = typeof params.lastActionTimestamp === "number" &&
|
|
1082
|
-
Number.isFinite(params.lastActionTimestamp)
|
|
1083
|
-
? new Date(params.lastActionTimestamp).toISOString()
|
|
1084
|
-
: "No recorded assistant actions yet";
|
|
1085
|
-
return [
|
|
1086
|
-
`Your reportee "@${params.subjectAgentId}" (${params.subjectName}) has no activity in the last ${params.inactiveMinutes} minutes.`,
|
|
1087
|
-
`Role: ${params.role}`,
|
|
1088
|
-
`Last action: ${lastAction}`,
|
|
1089
|
-
`Manager: @${params.managerAgentId}`,
|
|
1090
|
-
"Please check in and unblock progress.",
|
|
1091
|
-
].join("\n");
|
|
1092
|
-
}
|
|
1093
|
-
function assertAgentExists(manifests, agentId) {
|
|
1094
|
-
if (manifests.some((manifest) => manifest.agentId === agentId)) {
|
|
1095
|
-
return;
|
|
1096
|
-
}
|
|
1097
|
-
throw new Error(`Agent "${agentId}" does not exist.`);
|
|
1098
|
-
}
|
|
1099
|
-
function collectAllReportees(manifests, managerAgentId) {
|
|
1100
|
-
const byManager = new Map();
|
|
1101
|
-
for (const manifest of manifests) {
|
|
1102
|
-
const reportsTo = manifest.metadata.reportsTo;
|
|
1103
|
-
if (!reportsTo) {
|
|
1104
|
-
continue;
|
|
1105
|
-
}
|
|
1106
|
-
const reportees = byManager.get(reportsTo) ?? [];
|
|
1107
|
-
reportees.push(manifest.agentId);
|
|
1108
|
-
byManager.set(reportsTo, reportees);
|
|
1109
|
-
}
|
|
1110
|
-
const visited = new Set();
|
|
1111
|
-
const queue = [...(byManager.get(managerAgentId) ?? [])];
|
|
1112
|
-
while (queue.length > 0) {
|
|
1113
|
-
const current = queue.shift();
|
|
1114
|
-
if (!current || current === managerAgentId || visited.has(current)) {
|
|
1115
|
-
continue;
|
|
1116
|
-
}
|
|
1117
|
-
visited.add(current);
|
|
1118
|
-
queue.push(...(byManager.get(current) ?? []));
|
|
1119
|
-
}
|
|
1120
|
-
return [...visited].sort((left, right) => left.localeCompare(right));
|
|
1121
|
-
}
|
|
1122
|
-
function prepareOpenClawCommandEnv(env) {
|
|
1123
|
-
const mergedPath = dedupePathEntries([
|
|
1124
|
-
...resolvePreferredOpenClawCommandPaths(env),
|
|
1125
|
-
...(env.PATH?.split(path.delimiter) ?? []),
|
|
1126
|
-
]);
|
|
1127
|
-
return {
|
|
1128
|
-
...env,
|
|
1129
|
-
PATH: mergedPath.join(path.delimiter),
|
|
1130
|
-
};
|
|
1131
|
-
}
|
|
1132
|
-
function resolvePreferredOpenClawCommandPaths(env) {
|
|
1133
|
-
const homeDir = homedir();
|
|
1134
|
-
const preferredPaths = [
|
|
1135
|
-
path.dirname(process.execPath),
|
|
1136
|
-
path.join(homeDir, ".npm-global", "bin"),
|
|
1137
|
-
path.join(homeDir, ".npm", "bin"),
|
|
1138
|
-
path.join(homeDir, ".local", "bin"),
|
|
1139
|
-
path.join(homeDir, ".volta", "bin"),
|
|
1140
|
-
path.join(homeDir, ".fnm", "current", "bin"),
|
|
1141
|
-
path.join(homeDir, ".asdf", "shims"),
|
|
1142
|
-
path.join(homeDir, "bin"),
|
|
1143
|
-
];
|
|
1144
|
-
const npmPrefixCandidates = dedupePathEntries([
|
|
1145
|
-
env.npm_config_prefix ?? "",
|
|
1146
|
-
env.NPM_CONFIG_PREFIX ?? "",
|
|
1147
|
-
process.env.npm_config_prefix ?? "",
|
|
1148
|
-
process.env.NPM_CONFIG_PREFIX ?? "",
|
|
1149
|
-
]);
|
|
1150
|
-
for (const prefix of npmPrefixCandidates) {
|
|
1151
|
-
preferredPaths.push(path.join(prefix, "bin"));
|
|
1152
|
-
}
|
|
1153
|
-
if (process.platform === "darwin") {
|
|
1154
|
-
preferredPaths.push("/opt/homebrew/bin", "/opt/homebrew/opt/node@22/bin", "/usr/local/opt/node@22/bin");
|
|
1155
|
-
}
|
|
1156
|
-
return preferredPaths;
|
|
1157
|
-
}
|
|
1158
|
-
function dedupePathEntries(entries) {
|
|
1159
|
-
const seen = new Set();
|
|
1160
|
-
const deduped = [];
|
|
1161
|
-
for (const rawEntry of entries) {
|
|
1162
|
-
const entry = rawEntry.trim();
|
|
1163
|
-
if (!entry || seen.has(entry)) {
|
|
1164
|
-
continue;
|
|
1165
|
-
}
|
|
1166
|
-
seen.add(entry);
|
|
1167
|
-
deduped.push(entry);
|
|
1168
|
-
}
|
|
1169
|
-
return deduped;
|
|
1170
|
-
}
|
|
1171
|
-
function isSpawnPermissionOrMissing(error) {
|
|
1172
|
-
return (typeof error === "object" &&
|
|
1173
|
-
error !== null &&
|
|
1174
|
-
"code" in error &&
|
|
1175
|
-
((error.code ?? "") === "ENOENT" ||
|
|
1176
|
-
(error.code ?? "") === "EACCES"));
|
|
1177
971
|
}
|
|
1178
972
|
//# sourceMappingURL=opengoat.service.js.map
|