@opengoat/core 2026.2.18-2 → 2026.2.20
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 +11 -0
- package/dist/core/agents/application/agent.service.js +129 -15
- package/dist/core/agents/application/agent.service.js.map +1 -1
- package/dist/core/boards/application/board.service.d.ts +8 -1
- package/dist/core/boards/application/board.service.js +262 -38
- package/dist/core/boards/application/board.service.js.map +1 -1
- package/dist/core/boards/domain/board.d.ts +1 -2
- package/dist/core/bootstrap/application/bootstrap.service.js +4 -0
- package/dist/core/bootstrap/application/bootstrap.service.js.map +1 -1
- package/dist/core/opengoat/application/opengoat.service.d.ts +6 -1
- package/dist/core/opengoat/application/opengoat.service.helpers.d.ts +52 -0
- package/dist/core/opengoat/application/opengoat.service.helpers.js +129 -3
- package/dist/core/opengoat/application/opengoat.service.helpers.js.map +1 -1
- package/dist/core/opengoat/application/opengoat.service.js +310 -47
- package/dist/core/opengoat/application/opengoat.service.js.map +1 -1
- package/dist/core/orchestration/application/orchestration.service.js +6 -1
- package/dist/core/orchestration/application/orchestration.service.js.map +1 -1
- package/dist/core/ports/file-system.port.d.ts +3 -0
- package/dist/core/providers/application/provider.service.d.ts +3 -0
- package/dist/core/providers/application/provider.service.js +126 -0
- package/dist/core/providers/application/provider.service.js.map +1 -1
- package/dist/core/providers/cli-provider.d.ts +1 -0
- package/dist/core/providers/cli-provider.js +11 -8
- package/dist/core/providers/cli-provider.js.map +1 -1
- package/dist/core/providers/openclaw-gateway-rpc.js +70 -17
- package/dist/core/providers/openclaw-gateway-rpc.js.map +1 -1
- package/dist/core/providers/providers/codex/provider.d.ts +1 -0
- package/dist/core/providers/providers/codex/provider.js +24 -0
- package/dist/core/providers/providers/codex/provider.js.map +1 -1
- package/dist/core/providers/providers/copilot-cli/index.d.ts +4 -0
- package/dist/core/providers/providers/copilot-cli/index.js +37 -0
- package/dist/core/providers/providers/copilot-cli/index.js.map +1 -0
- package/dist/core/providers/providers/copilot-cli/provider.d.ts +6 -0
- package/dist/core/providers/providers/copilot-cli/provider.js +39 -0
- package/dist/core/providers/providers/copilot-cli/provider.js.map +1 -0
- package/dist/core/providers/providers/registry.js +2 -0
- package/dist/core/providers/providers/registry.js.map +1 -1
- package/dist/core/providers/types.d.ts +1 -0
- package/dist/core/templates/assets/ceo/BOOTSTRAP.md +3 -3
- package/dist/core/templates/assets/ceo/ROLE.md +4 -4
- package/dist/core/templates/assets/skills/og-board-manager/SKILL.md +3 -6
- package/dist/platform/node/node-file-system.d.ts +3 -0
- package/dist/platform/node/node-file-system.js +30 -1
- package/dist/platform/node/node-file-system.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,15 +10,21 @@ import { ProviderCommandNotFoundError, createDefaultProviderRegistry, } from "..
|
|
|
10
10
|
import { dirname, resolve as resolvePath } from "node:path";
|
|
11
11
|
import { SessionService, } from "../../sessions/index.js";
|
|
12
12
|
import { SkillService, } from "../../skills/index.js";
|
|
13
|
-
import { assertAgentExists, buildBlockedTaskMessage, buildInactiveAgentsMessage, buildNotificationSessionRef, buildPendingTaskMessage, buildReporteeStats, buildTodoTaskMessage, collectAllReportees, containsAgentNotFoundMessage, containsAlreadyExistsMessage, extractManagedSkillsDir, extractOpenClawAgents, isSpawnPermissionOrMissing, pathIsWithin, pathMatches, prepareOpenClawCommandEnv,
|
|
13
|
+
import { assertAgentExists, buildBlockedTaskMessage, buildDoingTaskMessage, buildInactiveAgentsMessage, buildNotificationSessionRef, buildPendingTaskMessage, buildReporteeStats, buildTopDownTaskDelegationMessage, buildTodoTaskMessage, collectAllReportees, containsAgentNotFoundMessage, containsAlreadyExistsMessage, extractManagedSkillsDir, extractOpenClawAgents, isSpawnPermissionOrMissing, pathIsWithin, pathMatches, prepareOpenClawCommandEnv, resolveInProgressTimeoutMinutes, resolveBottomUpTaskDelegationStrategy, resolveTopDownTaskDelegationStrategy, resolveMaxParallelFlows, toErrorMessage, } from "./opengoat.service.helpers.js";
|
|
14
14
|
const OPENCLAW_PROVIDER_ID = "openclaw";
|
|
15
15
|
const OPENCLAW_DEFAULT_AGENT_ID = "main";
|
|
16
16
|
const OPENCLAW_AGENT_SANDBOX_MODE = "off";
|
|
17
17
|
const OPENCLAW_AGENT_TOOLS_ALLOW_ALL_JSON = "[\"*\"]";
|
|
18
|
+
const OPENCLAW_AGENT_SKIP_BOOTSTRAP = true;
|
|
18
19
|
const OPENCLAW_OPENGOAT_PLUGIN_ID = "openclaw-plugin";
|
|
19
20
|
const OPENCLAW_OPENGOAT_PLUGIN_ROOT_ID = "opengoat-plugin";
|
|
20
21
|
const OPENCLAW_OPENGOAT_PLUGIN_LEGACY_PACK_ID = "openclaw-plugin-pack";
|
|
21
22
|
const OPENCLAW_OPENGOAT_PLUGIN_FALLBACK_ID = "workspace";
|
|
23
|
+
const NOTIFICATION_SESSION_COMPACTION_COMMAND = [
|
|
24
|
+
"/compact",
|
|
25
|
+
"Keep only the last 3 notification exchanges plus active task ids, statuses, blockers, and explicit next actions.",
|
|
26
|
+
"Remove redundant older notification chatter.",
|
|
27
|
+
].join(" ");
|
|
22
28
|
export class OpenGoatService {
|
|
23
29
|
fileSystem;
|
|
24
30
|
pathPort;
|
|
@@ -205,23 +211,31 @@ export class OpenGoatService {
|
|
|
205
211
|
warnings.push(`OpenClaw role skill assignment sync for "ceo" failed: ${toErrorMessage(error)}`);
|
|
206
212
|
}
|
|
207
213
|
let openClawAgentEntriesById;
|
|
214
|
+
let openClawInventoryAvailable = false;
|
|
208
215
|
try {
|
|
209
216
|
openClawAgentEntriesById = new Map((await this.listOpenClawAgents(paths)).map((entry) => [entry.id, entry]));
|
|
217
|
+
openClawInventoryAvailable = true;
|
|
210
218
|
}
|
|
211
219
|
catch (error) {
|
|
212
220
|
warnings.push(`OpenClaw startup inventory check failed: ${toErrorMessage(error)}`);
|
|
213
221
|
}
|
|
214
222
|
try {
|
|
215
223
|
localAgents = await this.agentService.listAgents(paths);
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
224
|
+
if (!openClawInventoryAvailable) {
|
|
225
|
+
warnings.push("OpenClaw startup registration sync skipped because agent inventory is unavailable.");
|
|
226
|
+
ceoSynced = localAgents.some((agent) => agent.id === DEFAULT_AGENT_ID);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
for (const agent of localAgents) {
|
|
230
|
+
const sync = await this.syncOpenClawAgentRegistration(paths, {
|
|
231
|
+
descriptor: agent,
|
|
232
|
+
existingEntry: openClawAgentEntriesById?.get(agent.id),
|
|
233
|
+
});
|
|
234
|
+
warnings.push(...sync.warnings);
|
|
235
|
+
if (agent.id === DEFAULT_AGENT_ID) {
|
|
236
|
+
ceoSynced = sync.synced;
|
|
237
|
+
ceoSyncCode = sync.code;
|
|
238
|
+
}
|
|
225
239
|
}
|
|
226
240
|
}
|
|
227
241
|
}
|
|
@@ -249,6 +263,12 @@ export class OpenGoatService {
|
|
|
249
263
|
catch (error) {
|
|
250
264
|
warnings.push(`OpenGoat workspace command shim sync failed: ${toErrorMessage(error)}`);
|
|
251
265
|
}
|
|
266
|
+
try {
|
|
267
|
+
await this.agentService.syncWorkspaceReporteeLinks(paths);
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
warnings.push(`OpenGoat workspace reportees sync failed: ${toErrorMessage(error)}`);
|
|
271
|
+
}
|
|
252
272
|
return {
|
|
253
273
|
ceoSyncCode,
|
|
254
274
|
ceoSynced,
|
|
@@ -308,24 +328,35 @@ export class OpenGoatService {
|
|
|
308
328
|
throw new Error(`OpenClaw agent location sync failed for "${created.agent.id}". ${toErrorMessage(error)}`);
|
|
309
329
|
}
|
|
310
330
|
await this.syncOpenClawAgentExecutionPolicies(paths, [created.agent.id]);
|
|
331
|
+
if (!created.alreadyExisted) {
|
|
332
|
+
try {
|
|
333
|
+
const workspaceBootstrap = await this.agentService.ensureAgentWorkspaceBootstrap(paths, {
|
|
334
|
+
agentId: created.agent.id,
|
|
335
|
+
displayName: created.agent.displayName,
|
|
336
|
+
role: options.role?.trim() ?? "",
|
|
337
|
+
}, {
|
|
338
|
+
syncBootstrapMarkdown: false,
|
|
339
|
+
});
|
|
340
|
+
created.createdPaths.push(...workspaceBootstrap.createdPaths);
|
|
341
|
+
created.skippedPaths.push(...workspaceBootstrap.skippedPaths);
|
|
342
|
+
created.skippedPaths.push(...workspaceBootstrap.removedPaths);
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
await this.agentService.removeAgent(paths, created.agent.id);
|
|
346
|
+
throw new Error(`Failed to update workspace bootstrap for "${created.agent.id}". ${toErrorMessage(error)}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
311
349
|
try {
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
(created.alreadyExisted ? created.agent.role : ""),
|
|
317
|
-
}, {
|
|
318
|
-
syncBootstrapMarkdown: false,
|
|
319
|
-
});
|
|
320
|
-
created.createdPaths.push(...workspaceBootstrap.createdPaths);
|
|
321
|
-
created.skippedPaths.push(...workspaceBootstrap.skippedPaths);
|
|
322
|
-
created.skippedPaths.push(...workspaceBootstrap.removedPaths);
|
|
350
|
+
const workspaceReporteesSync = await this.agentService.syncWorkspaceReporteeLinks(paths);
|
|
351
|
+
created.createdPaths.push(...workspaceReporteesSync.createdPaths);
|
|
352
|
+
created.skippedPaths.push(...workspaceReporteesSync.skippedPaths);
|
|
353
|
+
created.skippedPaths.push(...workspaceReporteesSync.removedPaths);
|
|
323
354
|
}
|
|
324
355
|
catch (error) {
|
|
325
356
|
if (!created.alreadyExisted) {
|
|
326
357
|
await this.agentService.removeAgent(paths, created.agent.id);
|
|
327
358
|
}
|
|
328
|
-
throw new Error(`Failed to
|
|
359
|
+
throw new Error(`Failed to sync reportees workspace links for "${created.agent.id}". ${toErrorMessage(error)}`);
|
|
329
360
|
}
|
|
330
361
|
return {
|
|
331
362
|
...created,
|
|
@@ -354,6 +385,7 @@ export class OpenGoatService {
|
|
|
354
385
|
throw new Error(`OpenClaw agent deletion failed for "${agentId}" (exit ${runtimeSync.code}). ${runtimeSync.stderr.trim() || runtimeSync.stdout.trim() || ""}`.trim());
|
|
355
386
|
}
|
|
356
387
|
const removed = await this.agentService.removeAgent(paths, agentId);
|
|
388
|
+
await this.agentService.syncWorkspaceReporteeLinks(paths);
|
|
357
389
|
return {
|
|
358
390
|
...removed,
|
|
359
391
|
runtimeSync: {
|
|
@@ -378,6 +410,7 @@ export class OpenGoatService {
|
|
|
378
410
|
if (updated.reportsTo) {
|
|
379
411
|
await this.syncOpenClawRoleSkills(paths, updated.reportsTo);
|
|
380
412
|
}
|
|
413
|
+
await this.agentService.syncWorkspaceReporteeLinks(paths);
|
|
381
414
|
return updated;
|
|
382
415
|
}
|
|
383
416
|
async listAgents() {
|
|
@@ -555,18 +588,23 @@ export class OpenGoatService {
|
|
|
555
588
|
const paths = this.pathsProvider.getPaths();
|
|
556
589
|
const ranAt = this.resolveNowIso();
|
|
557
590
|
const manifests = await this.agentManifestService.listManifests(paths);
|
|
558
|
-
const
|
|
559
|
-
const
|
|
560
|
-
const
|
|
591
|
+
const inProgressMinutes = resolveInProgressTimeoutMinutes(options.inProgressMinutes);
|
|
592
|
+
const topDownStrategy = resolveTopDownTaskDelegationStrategy(options);
|
|
593
|
+
const bottomUpStrategy = resolveBottomUpTaskDelegationStrategy(options);
|
|
561
594
|
const maxParallelFlows = resolveMaxParallelFlows(options.maxParallelFlows);
|
|
562
|
-
const inactiveCandidates =
|
|
563
|
-
? await this.collectInactiveAgents(paths, manifests, inactiveMinutes, notificationTarget)
|
|
595
|
+
const inactiveCandidates = bottomUpStrategy.enabled
|
|
596
|
+
? await this.collectInactiveAgents(paths, manifests, bottomUpStrategy.inactiveMinutes, bottomUpStrategy.notificationTarget)
|
|
564
597
|
: [];
|
|
565
598
|
const tasks = await this.boardService.listTasks(paths, { limit: 10_000 });
|
|
566
|
-
const
|
|
567
|
-
|
|
568
|
-
|
|
599
|
+
const topDownDispatches = topDownStrategy.enabled
|
|
600
|
+
? await this.dispatchTopDownTaskDelegationAutomations(paths, tasks, manifests, topDownStrategy.openTasksThreshold, ranAt, maxParallelFlows)
|
|
601
|
+
: [];
|
|
602
|
+
const pendingTaskIds = new Set(await this.boardService.listPendingTaskIdsOlderThan(paths, bottomUpStrategy.inactiveMinutes));
|
|
603
|
+
const doingTaskIds = new Set(await this.boardService.listDoingTaskIdsOlderThan(paths, inProgressMinutes));
|
|
604
|
+
const taskStatusDispatch = await this.dispatchTaskStatusAutomations(paths, tasks, manifests, doingTaskIds, pendingTaskIds, inProgressMinutes, bottomUpStrategy.inactiveMinutes, ranAt, maxParallelFlows);
|
|
605
|
+
const inactiveDispatches = await this.dispatchInactiveAgentAutomations(paths, inactiveCandidates, bottomUpStrategy.inactiveMinutes, ranAt, maxParallelFlows);
|
|
569
606
|
const dispatches = [
|
|
607
|
+
...topDownDispatches,
|
|
570
608
|
...taskStatusDispatch.dispatches,
|
|
571
609
|
...inactiveDispatches,
|
|
572
610
|
];
|
|
@@ -575,6 +613,7 @@ export class OpenGoatService {
|
|
|
575
613
|
ranAt,
|
|
576
614
|
scannedTasks: tasks.length,
|
|
577
615
|
todoTasks: taskStatusDispatch.todoTasks,
|
|
616
|
+
doingTasks: taskStatusDispatch.doingTasks,
|
|
578
617
|
blockedTasks: taskStatusDispatch.blockedTasks,
|
|
579
618
|
inactiveAgents: inactiveCandidates.length,
|
|
580
619
|
sent: dispatches.length - failed,
|
|
@@ -582,13 +621,71 @@ export class OpenGoatService {
|
|
|
582
621
|
dispatches,
|
|
583
622
|
};
|
|
584
623
|
}
|
|
585
|
-
async
|
|
624
|
+
async dispatchTopDownTaskDelegationAutomations(paths, tasks, manifests, openTasksThreshold, notificationTimestamp, maxParallelFlows = 1) {
|
|
625
|
+
const openTasks = tasks
|
|
626
|
+
.filter((task) => isTopDownOpenTaskStatus(task.status))
|
|
627
|
+
.sort((left, right) => {
|
|
628
|
+
const leftTimestamp = Date.parse(left.updatedAt);
|
|
629
|
+
const rightTimestamp = Date.parse(right.updatedAt);
|
|
630
|
+
if (Number.isFinite(leftTimestamp) && Number.isFinite(rightTimestamp)) {
|
|
631
|
+
return rightTimestamp - leftTimestamp;
|
|
632
|
+
}
|
|
633
|
+
if (Number.isFinite(rightTimestamp)) {
|
|
634
|
+
return 1;
|
|
635
|
+
}
|
|
636
|
+
if (Number.isFinite(leftTimestamp)) {
|
|
637
|
+
return -1;
|
|
638
|
+
}
|
|
639
|
+
return right.taskId.localeCompare(left.taskId);
|
|
640
|
+
});
|
|
641
|
+
if (openTasks.length > openTasksThreshold) {
|
|
642
|
+
return [];
|
|
643
|
+
}
|
|
644
|
+
const managerAgents = manifests.filter((manifest) => manifest.metadata.type === "manager").length;
|
|
645
|
+
const ceoDirectReportees = manifests.filter((manifest) => normalizeAgentId(manifest.metadata.reportsTo ?? "") === DEFAULT_AGENT_ID).length;
|
|
646
|
+
const sessionRef = buildNotificationSessionRef(DEFAULT_AGENT_ID);
|
|
647
|
+
const message = buildTopDownTaskDelegationMessage({
|
|
648
|
+
openTasksThreshold,
|
|
649
|
+
openTasksCount: openTasks.length,
|
|
650
|
+
totalAgents: manifests.length,
|
|
651
|
+
managerAgents,
|
|
652
|
+
ceoDirectReportees,
|
|
653
|
+
openTasks: openTasks.map((task) => ({
|
|
654
|
+
taskId: task.taskId,
|
|
655
|
+
title: task.title,
|
|
656
|
+
status: task.status,
|
|
657
|
+
assignedTo: task.assignedTo,
|
|
658
|
+
})),
|
|
659
|
+
notificationTimestamp,
|
|
660
|
+
});
|
|
661
|
+
const requests = [
|
|
662
|
+
{
|
|
663
|
+
targetAgentId: DEFAULT_AGENT_ID,
|
|
664
|
+
sessionRef,
|
|
665
|
+
message,
|
|
666
|
+
},
|
|
667
|
+
];
|
|
668
|
+
return runWithConcurrencyByKey(requests, maxParallelFlows, (request) => request.targetAgentId, async (request) => {
|
|
669
|
+
const result = await this.dispatchAutomationMessage(paths, request.targetAgentId, request.sessionRef, request.message);
|
|
670
|
+
return {
|
|
671
|
+
kind: "topdown",
|
|
672
|
+
targetAgentId: request.targetAgentId,
|
|
673
|
+
sessionRef: request.sessionRef,
|
|
674
|
+
message: request.message,
|
|
675
|
+
ok: result.ok,
|
|
676
|
+
error: result.error,
|
|
677
|
+
};
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
async dispatchTaskStatusAutomations(paths, tasks, manifests, doingTaskIds, pendingTaskIds, doingMinutes, pendingMinutes, notificationTimestamp, maxParallelFlows) {
|
|
586
681
|
const manifestsById = new Map(manifests.map((manifest) => [manifest.agentId, manifest]));
|
|
587
682
|
const requests = [];
|
|
588
683
|
let todoTasks = 0;
|
|
684
|
+
let doingTasks = 0;
|
|
589
685
|
let pendingTasks = 0;
|
|
590
686
|
let blockedTasks = 0;
|
|
591
|
-
|
|
687
|
+
const orderedTasks = [...tasks].sort(compareTaskCreatedAtAscending);
|
|
688
|
+
for (const task of orderedTasks) {
|
|
592
689
|
if (task.status === "todo") {
|
|
593
690
|
todoTasks += 1;
|
|
594
691
|
const targetAgentId = task.assignedTo;
|
|
@@ -606,6 +703,27 @@ export class OpenGoatService {
|
|
|
606
703
|
});
|
|
607
704
|
continue;
|
|
608
705
|
}
|
|
706
|
+
if (task.status === "doing") {
|
|
707
|
+
if (!doingTaskIds.has(task.taskId)) {
|
|
708
|
+
continue;
|
|
709
|
+
}
|
|
710
|
+
doingTasks += 1;
|
|
711
|
+
const targetAgentId = task.assignedTo;
|
|
712
|
+
const sessionRef = buildNotificationSessionRef(targetAgentId);
|
|
713
|
+
const message = buildDoingTaskMessage({
|
|
714
|
+
task,
|
|
715
|
+
doingMinutes,
|
|
716
|
+
notificationTimestamp,
|
|
717
|
+
});
|
|
718
|
+
requests.push({
|
|
719
|
+
kind: "doing",
|
|
720
|
+
targetAgentId,
|
|
721
|
+
sessionRef,
|
|
722
|
+
taskId: task.taskId,
|
|
723
|
+
message,
|
|
724
|
+
});
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
609
727
|
if (task.status === "pending") {
|
|
610
728
|
if (!pendingTaskIds.has(task.taskId)) {
|
|
611
729
|
continue;
|
|
@@ -658,9 +776,17 @@ export class OpenGoatService {
|
|
|
658
776
|
error: result.error,
|
|
659
777
|
};
|
|
660
778
|
});
|
|
779
|
+
const notifiedDoingTaskIds = dedupeStrings(dispatches
|
|
780
|
+
.filter((dispatch) => dispatch.kind === "doing" && dispatch.ok)
|
|
781
|
+
.map((dispatch) => dispatch.taskId)
|
|
782
|
+
.filter((taskId) => typeof taskId === "string"));
|
|
783
|
+
await Promise.all(notifiedDoingTaskIds.map(async (taskId) => {
|
|
784
|
+
await this.boardService.resetTaskStatusTimeout(paths, taskId, "doing");
|
|
785
|
+
}));
|
|
661
786
|
return {
|
|
662
787
|
dispatches,
|
|
663
788
|
todoTasks,
|
|
789
|
+
doingTasks,
|
|
664
790
|
pendingTasks,
|
|
665
791
|
blockedTasks,
|
|
666
792
|
};
|
|
@@ -796,14 +922,36 @@ export class OpenGoatService {
|
|
|
796
922
|
return this.pathsProvider.getPaths();
|
|
797
923
|
}
|
|
798
924
|
async dispatchAutomationMessage(paths, agentId, sessionRef, message, options = {}) {
|
|
925
|
+
const invoke = async (nextMessage) => this.runAgent(agentId, {
|
|
926
|
+
message: nextMessage,
|
|
927
|
+
sessionRef,
|
|
928
|
+
disableSession: options.disableSession ?? false,
|
|
929
|
+
cwd: options.cwd,
|
|
930
|
+
env: process.env,
|
|
931
|
+
});
|
|
799
932
|
try {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
933
|
+
let result = await invoke(message);
|
|
934
|
+
if (!isNotificationSessionRef(sessionRef) ||
|
|
935
|
+
options.disableSession === true ||
|
|
936
|
+
!isContextOverflowError(result.stderr, result.stdout)) {
|
|
937
|
+
if (result.code !== 0) {
|
|
938
|
+
return {
|
|
939
|
+
ok: false,
|
|
940
|
+
error: (result.stderr ||
|
|
941
|
+
result.stdout ||
|
|
942
|
+
`Runtime exited with code ${result.code}.`).trim(),
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
return { ok: true };
|
|
946
|
+
}
|
|
947
|
+
const binding = await this.providerService.getAgentProvider(paths, agentId);
|
|
948
|
+
if (binding.providerId === OPENCLAW_PROVIDER_ID &&
|
|
949
|
+
!message.trim().startsWith("/")) {
|
|
950
|
+
const compact = await invoke(NOTIFICATION_SESSION_COMPACTION_COMMAND);
|
|
951
|
+
if (compact.code === 0) {
|
|
952
|
+
result = await invoke(message);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
807
955
|
if (result.code !== 0) {
|
|
808
956
|
return {
|
|
809
957
|
ok: false,
|
|
@@ -1162,6 +1310,12 @@ export class OpenGoatService {
|
|
|
1162
1310
|
warnings.push(`OpenClaw tools policy sync failed for "${agentId}" (code ${toolsSet.code}). ${toolsSet.stderr.trim() || toolsSet.stdout.trim() || ""}`.trim());
|
|
1163
1311
|
}
|
|
1164
1312
|
}
|
|
1313
|
+
if (readAgentSkipBootstrap(entry) !== OPENCLAW_AGENT_SKIP_BOOTSTRAP) {
|
|
1314
|
+
const bootstrapSet = await this.runOpenClaw(["config", "set", `agents.list[${index}].skipBootstrap`, "true"], { env });
|
|
1315
|
+
if (bootstrapSet.code !== 0) {
|
|
1316
|
+
warnings.push(`OpenClaw bootstrap policy sync failed for "${agentId}" (code ${bootstrapSet.code}). ${bootstrapSet.stderr.trim() || bootstrapSet.stdout.trim() || ""}`.trim());
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1165
1319
|
}
|
|
1166
1320
|
return warnings;
|
|
1167
1321
|
}
|
|
@@ -1376,6 +1530,22 @@ function hasAgentToolsAllowAll(entry) {
|
|
|
1376
1530
|
}
|
|
1377
1531
|
return allow.some((value) => typeof value === "string" && value.trim() === "*");
|
|
1378
1532
|
}
|
|
1533
|
+
function readAgentSkipBootstrap(entry) {
|
|
1534
|
+
const value = entry.skipBootstrap;
|
|
1535
|
+
if (typeof value === "boolean") {
|
|
1536
|
+
return value;
|
|
1537
|
+
}
|
|
1538
|
+
if (typeof value === "string") {
|
|
1539
|
+
const normalized = value.trim().toLowerCase();
|
|
1540
|
+
if (normalized === "true") {
|
|
1541
|
+
return true;
|
|
1542
|
+
}
|
|
1543
|
+
if (normalized === "false") {
|
|
1544
|
+
return false;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
return undefined;
|
|
1548
|
+
}
|
|
1379
1549
|
function readStringArray(value) {
|
|
1380
1550
|
if (!Array.isArray(value)) {
|
|
1381
1551
|
return [];
|
|
@@ -1426,16 +1596,38 @@ async function runWithConcurrencyByKey(items, rawConcurrency, resolveKey, worker
|
|
|
1426
1596
|
});
|
|
1427
1597
|
return results;
|
|
1428
1598
|
}
|
|
1599
|
+
function compareTaskCreatedAtAscending(left, right) {
|
|
1600
|
+
const leftTimestamp = Date.parse(left.createdAt);
|
|
1601
|
+
const rightTimestamp = Date.parse(right.createdAt);
|
|
1602
|
+
if (Number.isFinite(leftTimestamp) && Number.isFinite(rightTimestamp)) {
|
|
1603
|
+
const timestampDiff = leftTimestamp - rightTimestamp;
|
|
1604
|
+
if (timestampDiff !== 0) {
|
|
1605
|
+
return timestampDiff;
|
|
1606
|
+
}
|
|
1607
|
+
return left.taskId.localeCompare(right.taskId);
|
|
1608
|
+
}
|
|
1609
|
+
if (Number.isFinite(leftTimestamp)) {
|
|
1610
|
+
return -1;
|
|
1611
|
+
}
|
|
1612
|
+
if (Number.isFinite(rightTimestamp)) {
|
|
1613
|
+
return 1;
|
|
1614
|
+
}
|
|
1615
|
+
return left.taskId.localeCompare(right.taskId);
|
|
1616
|
+
}
|
|
1429
1617
|
function parseLooseJson(raw) {
|
|
1430
1618
|
const trimmed = raw.trim();
|
|
1431
1619
|
if (!trimmed) {
|
|
1432
1620
|
return undefined;
|
|
1433
1621
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1622
|
+
const exact = tryParseJson(trimmed);
|
|
1623
|
+
if (exact !== undefined) {
|
|
1624
|
+
return exact;
|
|
1436
1625
|
}
|
|
1437
|
-
|
|
1438
|
-
|
|
1626
|
+
for (const line of trimmed.split(/\r?\n/)) {
|
|
1627
|
+
const parsedLine = tryParseJson(line.trim());
|
|
1628
|
+
if (parsedLine !== undefined) {
|
|
1629
|
+
return parsedLine;
|
|
1630
|
+
}
|
|
1439
1631
|
}
|
|
1440
1632
|
const starts = dedupeNumbers([
|
|
1441
1633
|
trimmed.indexOf("{"),
|
|
@@ -1448,11 +1640,69 @@ function parseLooseJson(raw) {
|
|
|
1448
1640
|
if (!candidate) {
|
|
1449
1641
|
continue;
|
|
1450
1642
|
}
|
|
1451
|
-
|
|
1452
|
-
|
|
1643
|
+
const parsedCandidate = tryParseJson(candidate);
|
|
1644
|
+
if (parsedCandidate !== undefined) {
|
|
1645
|
+
return parsedCandidate;
|
|
1453
1646
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
1647
|
+
const balancedCandidate = extractBalancedJsonCandidate(trimmed, startIndex);
|
|
1648
|
+
if (!balancedCandidate) {
|
|
1649
|
+
continue;
|
|
1650
|
+
}
|
|
1651
|
+
const parsedBalancedCandidate = tryParseJson(balancedCandidate);
|
|
1652
|
+
if (parsedBalancedCandidate !== undefined) {
|
|
1653
|
+
return parsedBalancedCandidate;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
return undefined;
|
|
1657
|
+
}
|
|
1658
|
+
function tryParseJson(raw) {
|
|
1659
|
+
if (!raw) {
|
|
1660
|
+
return undefined;
|
|
1661
|
+
}
|
|
1662
|
+
try {
|
|
1663
|
+
return JSON.parse(raw);
|
|
1664
|
+
}
|
|
1665
|
+
catch {
|
|
1666
|
+
return undefined;
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
function extractBalancedJsonCandidate(raw, startIndex) {
|
|
1670
|
+
const opening = raw[startIndex];
|
|
1671
|
+
if (opening !== "{" && opening !== "[") {
|
|
1672
|
+
return undefined;
|
|
1673
|
+
}
|
|
1674
|
+
const closing = opening === "{" ? "}" : "]";
|
|
1675
|
+
let depth = 0;
|
|
1676
|
+
let inString = false;
|
|
1677
|
+
let escaping = false;
|
|
1678
|
+
for (let index = startIndex; index < raw.length; index += 1) {
|
|
1679
|
+
const char = raw[index];
|
|
1680
|
+
if (inString) {
|
|
1681
|
+
if (escaping) {
|
|
1682
|
+
escaping = false;
|
|
1683
|
+
}
|
|
1684
|
+
else if (char === "\\") {
|
|
1685
|
+
escaping = true;
|
|
1686
|
+
}
|
|
1687
|
+
else if (char === "\"") {
|
|
1688
|
+
inString = false;
|
|
1689
|
+
}
|
|
1690
|
+
continue;
|
|
1691
|
+
}
|
|
1692
|
+
if (char === "\"") {
|
|
1693
|
+
inString = true;
|
|
1694
|
+
continue;
|
|
1695
|
+
}
|
|
1696
|
+
if (char === opening) {
|
|
1697
|
+
depth += 1;
|
|
1698
|
+
continue;
|
|
1699
|
+
}
|
|
1700
|
+
if (char !== closing) {
|
|
1701
|
+
continue;
|
|
1702
|
+
}
|
|
1703
|
+
depth -= 1;
|
|
1704
|
+
if (depth === 0) {
|
|
1705
|
+
return raw.slice(startIndex, index + 1).trim();
|
|
1456
1706
|
}
|
|
1457
1707
|
}
|
|
1458
1708
|
return undefined;
|
|
@@ -1526,4 +1776,17 @@ function isOpenGoatPluginId(pluginId) {
|
|
|
1526
1776
|
function isPluginNotFoundMessage(message) {
|
|
1527
1777
|
return message.toLowerCase().includes("plugin not found");
|
|
1528
1778
|
}
|
|
1779
|
+
function isNotificationSessionRef(sessionRef) {
|
|
1780
|
+
return sessionRef.trim().toLowerCase().endsWith("_notifications");
|
|
1781
|
+
}
|
|
1782
|
+
function isContextOverflowError(stderr, stdout) {
|
|
1783
|
+
const combined = `${stderr}\n${stdout}`.toLowerCase();
|
|
1784
|
+
return (combined.includes("context overflow") ||
|
|
1785
|
+
combined.includes("prompt too large") ||
|
|
1786
|
+
combined.includes("context length"));
|
|
1787
|
+
}
|
|
1788
|
+
function isTopDownOpenTaskStatus(status) {
|
|
1789
|
+
const normalized = status.trim().toLowerCase();
|
|
1790
|
+
return normalized !== "done" && normalized !== "blocked";
|
|
1791
|
+
}
|
|
1529
1792
|
//# sourceMappingURL=opengoat.service.js.map
|