@swarmclawai/swarmclaw 1.2.0 → 1.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/README.md +19 -0
- package/package.json +5 -2
- package/skills/coding-agent/SKILL.md +111 -0
- package/skills/github/SKILL.md +140 -0
- package/skills/nano-banana-pro/SKILL.md +62 -0
- package/skills/nano-banana-pro/scripts/generate_image.py +235 -0
- package/skills/nano-pdf/SKILL.md +53 -0
- package/skills/openai-image-gen/SKILL.md +78 -0
- package/skills/openai-image-gen/scripts/gen.py +328 -0
- package/skills/resourceful-problem-solving/SKILL.md +49 -0
- package/skills/skill-creator/SKILL.md +147 -0
- package/skills/skill-creator/scripts/init_skill.py +378 -0
- package/skills/skill-creator/scripts/quick_validate.py +159 -0
- package/skills/summarize/SKILL.md +77 -0
- package/src/app/api/auth/route.ts +20 -5
- package/src/app/api/chats/[id]/deploy/route.ts +11 -6
- package/src/app/api/chats/[id]/devserver/route.ts +17 -20
- package/src/app/api/chats/[id]/messages/route.ts +15 -11
- package/src/app/api/chats/[id]/route.ts +9 -10
- package/src/app/api/chats/[id]/stop/route.ts +5 -7
- package/src/app/api/chats/messages-route.test.ts +8 -6
- package/src/app/api/chats/route.ts +9 -10
- package/src/app/api/credentials/[id]/route.ts +4 -1
- package/src/app/api/extensions/marketplace/route.ts +5 -2
- package/src/app/api/ip/route.ts +2 -2
- package/src/app/api/memory/maintenance/route.ts +5 -2
- package/src/app/api/preview-server/route.ts +15 -12
- package/src/app/api/projects/[id]/route.ts +7 -46
- package/src/app/api/system/status/route.ts +11 -0
- package/src/app/api/upload/route.ts +4 -1
- package/src/cli/index.js +7 -0
- package/src/cli/spec.js +1 -0
- package/src/components/agents/agent-files-editor.tsx +44 -32
- package/src/components/agents/personality-builder.tsx +13 -7
- package/src/components/agents/trash-list.tsx +1 -1
- package/src/components/chat/chat-area.tsx +45 -23
- package/src/components/chat/message-bubble.test.ts +35 -0
- package/src/components/chat/message-bubble.tsx +20 -9
- package/src/components/chat/message-list.tsx +62 -42
- package/src/components/chat/swarm-status-card.tsx +10 -3
- package/src/components/input/chat-input.tsx +34 -14
- package/src/components/layout/daemon-indicator.tsx +7 -8
- package/src/components/layout/update-banner.tsx +8 -13
- package/src/components/logs/log-list.tsx +1 -1
- package/src/components/memory/memory-card.tsx +3 -1
- package/src/components/org-chart/org-chart-view.tsx +4 -0
- package/src/components/projects/project-list.tsx +4 -2
- package/src/components/projects/tabs/overview-tab.tsx +3 -2
- package/src/components/secrets/secret-sheet.tsx +1 -1
- package/src/components/secrets/secrets-list.tsx +1 -1
- package/src/components/shared/agent-switch-dialog.tsx +12 -6
- package/src/components/shared/dir-browser.tsx +22 -18
- package/src/components/skills/skill-sheet.tsx +2 -3
- package/src/components/tasks/task-list.tsx +1 -1
- package/src/components/tasks/task-sheet.tsx +1 -1
- package/src/hooks/use-openclaw-gateway.ts +46 -27
- package/src/instrumentation.ts +10 -7
- package/src/lib/chat/assistant-render-id.ts +3 -0
- package/src/lib/chat/chat-streaming-state.test.ts +42 -3
- package/src/lib/chat/chat-streaming-state.ts +20 -8
- package/src/lib/chat/chat.ts +18 -2
- package/src/lib/chat/queued-message-queue.test.ts +23 -1
- package/src/lib/chat/queued-message-queue.ts +11 -2
- package/src/lib/providers/anthropic.ts +6 -3
- package/src/lib/providers/claude-cli.ts +9 -3
- package/src/lib/providers/cli-utils.test.ts +124 -0
- package/src/lib/providers/cli-utils.ts +15 -0
- package/src/lib/providers/codex-cli.ts +9 -3
- package/src/lib/providers/gemini-cli.ts +6 -2
- package/src/lib/providers/index.ts +4 -1
- package/src/lib/providers/ollama.ts +5 -2
- package/src/lib/providers/openai.ts +8 -5
- package/src/lib/providers/opencode-cli.ts +6 -2
- package/src/lib/server/activity/activity-log.ts +21 -0
- package/src/lib/server/agents/agent-availability.test.ts +10 -5
- package/src/lib/server/agents/agent-cascade.ts +79 -59
- package/src/lib/server/agents/agent-registry.ts +23 -4
- package/src/lib/server/agents/agent-repository.ts +90 -0
- package/src/lib/server/agents/delegation-job-repository.ts +53 -0
- package/src/lib/server/agents/delegation-jobs.ts +11 -4
- package/src/lib/server/agents/guardian-checkpoint-repository.ts +35 -0
- package/src/lib/server/agents/guardian.ts +2 -2
- package/src/lib/server/agents/main-agent-loop.ts +14 -6
- package/src/lib/server/agents/main-loop-state-repository.ts +38 -0
- package/src/lib/server/agents/subagent-runtime.ts +9 -6
- package/src/lib/server/agents/subagent-swarm.ts +3 -2
- package/src/lib/server/agents/task-session.ts +3 -4
- package/src/lib/server/approvals/approval-repository.ts +30 -0
- package/src/lib/server/autonomy/supervisor-incident-repository.ts +42 -0
- package/src/lib/server/autonomy/supervisor-reflection.ts +14 -1
- package/src/lib/server/chat-execution/chat-execution-types.ts +38 -0
- package/src/lib/server/chat-execution/chat-execution-utils.ts +1 -1
- package/src/lib/server/chat-execution/chat-execution.ts +84 -1914
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +620 -0
- package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +221 -0
- package/src/lib/server/chat-execution/chat-turn-preflight.ts +133 -0
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +817 -0
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +296 -0
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +5 -5
- package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -3
- package/src/lib/server/chat-execution/continuation-limits.ts +6 -3
- package/src/lib/server/chat-execution/message-classifier.test.ts +329 -0
- package/src/lib/server/chat-execution/message-classifier.ts +5 -2
- package/src/lib/server/chat-execution/post-stream-finalization.ts +5 -2
- package/src/lib/server/chat-execution/prompt-builder.ts +22 -1
- package/src/lib/server/chat-execution/prompt-sections.ts +55 -13
- package/src/lib/server/chat-execution/response-completeness.ts +5 -2
- package/src/lib/server/chat-execution/situational-awareness.ts +12 -7
- package/src/lib/server/chat-execution/stream-agent-chat.ts +58 -25
- package/src/lib/server/chatrooms/chatroom-memory-bridge.ts +6 -3
- package/src/lib/server/chatrooms/chatroom-repository.ts +32 -0
- package/src/lib/server/connectors/bluebubbles.ts +7 -4
- package/src/lib/server/connectors/connector-inbound.ts +16 -13
- package/src/lib/server/connectors/connector-lifecycle.ts +11 -8
- package/src/lib/server/connectors/connector-outbound.ts +6 -3
- package/src/lib/server/connectors/connector-repository.ts +58 -0
- package/src/lib/server/connectors/discord.ts +10 -7
- package/src/lib/server/connectors/email.ts +17 -14
- package/src/lib/server/connectors/googlechat.ts +7 -4
- package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -2
- package/src/lib/server/connectors/matrix.ts +6 -3
- package/src/lib/server/connectors/openclaw.ts +20 -17
- package/src/lib/server/connectors/outbox.ts +4 -1
- package/src/lib/server/connectors/runtime-state.test.ts +117 -0
- package/src/lib/server/connectors/runtime-state.ts +19 -0
- package/src/lib/server/connectors/session-consolidation.ts +5 -2
- package/src/lib/server/connectors/signal.ts +9 -6
- package/src/lib/server/connectors/slack.ts +13 -10
- package/src/lib/server/connectors/teams.ts +8 -5
- package/src/lib/server/connectors/telegram.ts +15 -12
- package/src/lib/server/connectors/whatsapp.ts +32 -29
- package/src/lib/server/credentials/credential-repository.ts +7 -0
- package/src/lib/server/embeddings.ts +4 -1
- package/src/lib/server/gateways/gateway-profile-repository.ts +4 -0
- package/src/lib/server/link-understanding.ts +4 -1
- package/src/lib/server/memory/memory-abstract.test.ts +59 -0
- package/src/lib/server/memory/memory-abstract.ts +59 -0
- package/src/lib/server/memory/memory-db.ts +40 -14
- package/src/lib/server/missions/mission-repository.ts +74 -0
- package/src/lib/server/missions/mission-service/actions.ts +6 -0
- package/src/lib/server/missions/mission-service/bindings.ts +9 -0
- package/src/lib/server/missions/mission-service/context.ts +4 -0
- package/src/lib/server/missions/mission-service/core.ts +2269 -0
- package/src/lib/server/missions/mission-service/queries.ts +12 -0
- package/src/lib/server/missions/mission-service/recovery.ts +5 -0
- package/src/lib/server/missions/mission-service/ticks.ts +9 -0
- package/src/lib/server/missions/mission-service.test.ts +9 -2
- package/src/lib/server/missions/mission-service.ts +6 -2263
- package/src/lib/server/openclaw/gateway.ts +8 -5
- package/src/lib/server/persistence/repository-utils.ts +154 -0
- package/src/lib/server/persistence/storage-context.ts +51 -0
- package/src/lib/server/persistence/transaction.ts +1 -0
- package/src/lib/server/project-utils.ts +13 -0
- package/src/lib/server/projects/project-repository.ts +36 -0
- package/src/lib/server/projects/project-service.ts +79 -0
- package/src/lib/server/protocols/protocol-agent-turn.ts +5 -2
- package/src/lib/server/protocols/protocol-normalization.test.ts +6 -4
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +5 -2
- package/src/lib/server/protocols/protocol-step-helpers.ts +4 -1
- package/src/lib/server/provider-health.ts +18 -0
- package/src/lib/server/query-expansion.ts +4 -1
- package/src/lib/server/runtime/alert-dispatch.ts +8 -7
- package/src/lib/server/runtime/daemon-policy.ts +1 -1
- package/src/lib/server/runtime/daemon-state/core.ts +1570 -0
- package/src/lib/server/runtime/daemon-state/health.ts +6 -0
- package/src/lib/server/runtime/daemon-state/policy.ts +7 -0
- package/src/lib/server/runtime/daemon-state/supervisor.ts +6 -0
- package/src/lib/server/runtime/daemon-state.test.ts +48 -0
- package/src/lib/server/runtime/daemon-state.ts +3 -1331
- package/src/lib/server/runtime/estop-repository.ts +4 -0
- package/src/lib/server/runtime/estop.ts +3 -1
- package/src/lib/server/runtime/heartbeat-service.test.ts +2 -2
- package/src/lib/server/runtime/heartbeat-service.ts +78 -34
- package/src/lib/server/runtime/heartbeat-wake.ts +6 -4
- package/src/lib/server/runtime/idle-window.ts +6 -3
- package/src/lib/server/runtime/network.ts +11 -0
- package/src/lib/server/runtime/orchestrator-events.ts +2 -2
- package/src/lib/server/runtime/perf.ts +4 -1
- package/src/lib/server/runtime/process-manager.ts +7 -4
- package/src/lib/server/runtime/queue/claims.ts +4 -0
- package/src/lib/server/runtime/queue/core.ts +2079 -0
- package/src/lib/server/runtime/queue/execution.ts +7 -0
- package/src/lib/server/runtime/queue/followups.ts +4 -0
- package/src/lib/server/runtime/queue/queries.ts +12 -0
- package/src/lib/server/runtime/queue/recovery.ts +7 -0
- package/src/lib/server/runtime/queue-recovery.test.ts +48 -13
- package/src/lib/server/runtime/queue-repository.ts +17 -0
- package/src/lib/server/runtime/queue.ts +5 -2058
- package/src/lib/server/runtime/run-ledger.ts +6 -5
- package/src/lib/server/runtime/run-repository.ts +73 -0
- package/src/lib/server/runtime/runtime-lock-repository.ts +8 -0
- package/src/lib/server/runtime/runtime-settings.ts +1 -1
- package/src/lib/server/runtime/runtime-state.ts +99 -0
- package/src/lib/server/runtime/scheduler.ts +13 -8
- package/src/lib/server/runtime/session-run-manager/cancellation.ts +157 -0
- package/src/lib/server/runtime/session-run-manager/drain.ts +246 -0
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +287 -0
- package/src/lib/server/runtime/session-run-manager/queries.ts +117 -0
- package/src/lib/server/runtime/session-run-manager/recovery.ts +238 -0
- package/src/lib/server/runtime/session-run-manager/state.ts +441 -0
- package/src/lib/server/runtime/session-run-manager/types.ts +74 -0
- package/src/lib/server/runtime/session-run-manager.ts +72 -1374
- package/src/lib/server/runtime/watch-job-repository.ts +35 -0
- package/src/lib/server/runtime/watch-jobs.ts +3 -1
- package/src/lib/server/sandbox/bridge-auth-registry.ts +6 -0
- package/src/lib/server/sandbox/novnc-auth.ts +10 -0
- package/src/lib/server/schedules/schedule-repository.ts +42 -0
- package/src/lib/server/session-tools/context.ts +14 -0
- package/src/lib/server/session-tools/discovery.ts +9 -6
- package/src/lib/server/session-tools/index.ts +3 -1
- package/src/lib/server/session-tools/platform.ts +1 -1
- package/src/lib/server/session-tools/subagent.ts +23 -2
- package/src/lib/server/session-tools/wallet.ts +4 -1
- package/src/lib/server/sessions/session-repository.ts +85 -0
- package/src/lib/server/settings/settings-repository.ts +25 -0
- package/src/lib/server/skills/clawhub-client.ts +4 -1
- package/src/lib/server/skills/runtime-skill-resolver.ts +8 -2
- package/src/lib/server/skills/skill-discovery.test.ts +2 -2
- package/src/lib/server/skills/skill-discovery.ts +2 -2
- package/src/lib/server/skills/skill-eligibility.ts +6 -0
- package/src/lib/server/skills/skill-repository.ts +14 -0
- package/src/lib/server/solana.ts +6 -0
- package/src/lib/server/storage-auth.ts +5 -5
- package/src/lib/server/storage-normalization.ts +4 -0
- package/src/lib/server/storage.ts +32 -32
- package/src/lib/server/tasks/task-followups.ts +4 -1
- package/src/lib/server/tasks/task-repository.ts +54 -0
- package/src/lib/server/tool-loop-detection.ts +8 -3
- package/src/lib/server/tool-planning.ts +226 -0
- package/src/lib/server/tool-retry.ts +4 -3
- package/src/lib/server/usage/usage-repository.ts +30 -0
- package/src/lib/server/wallet/wallet-portfolio.ts +29 -0
- package/src/lib/server/webhooks/webhook-repository.ts +10 -0
- package/src/lib/server/ws-hub.ts +5 -2
- package/src/lib/strip-internal-metadata.test.ts +78 -37
- package/src/lib/strip-internal-metadata.ts +20 -6
- package/src/stores/use-approval-store.ts +7 -1
- package/src/stores/use-chat-store.test.ts +54 -0
- package/src/stores/use-chat-store.ts +26 -6
- package/src/types/index.ts +6 -0
- /package/{bundled-skills → skills}/google-workspace/SKILL.md +0 -0
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import assert from 'node:assert/strict'
|
|
2
2
|
import { describe, it } from 'node:test'
|
|
3
|
+
import type { Agent, ProviderType } from '@/types'
|
|
3
4
|
import { isWorkerOnlyAgent, buildWorkerOnlyAgentMessage } from './agent-availability'
|
|
4
5
|
|
|
5
6
|
describe('isWorkerOnlyAgent', () => {
|
|
6
|
-
const CLI_PROVIDERS = ['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'openclaw']
|
|
7
|
-
const NON_CLI_PROVIDERS = ['openai', 'anthropic', 'google', 'deepseek', 'groq', '
|
|
7
|
+
const CLI_PROVIDERS = ['claude-cli', 'codex-cli', 'opencode-cli', 'gemini-cli', 'openclaw'] satisfies ProviderType[]
|
|
8
|
+
const NON_CLI_PROVIDERS = ['openai', 'anthropic', 'google', 'deepseek', 'groq', 'together'] satisfies ProviderType[]
|
|
9
|
+
|
|
10
|
+
function withProvider(provider: unknown): Pick<Agent, 'provider'> {
|
|
11
|
+
return { provider } as Pick<Agent, 'provider'>
|
|
12
|
+
}
|
|
8
13
|
|
|
9
14
|
for (const provider of CLI_PROVIDERS) {
|
|
10
15
|
it(`returns true for ${provider}`, () => {
|
|
11
|
-
assert.equal(isWorkerOnlyAgent(
|
|
16
|
+
assert.equal(isWorkerOnlyAgent(withProvider(provider)), true)
|
|
12
17
|
})
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
for (const provider of NON_CLI_PROVIDERS) {
|
|
16
21
|
it(`returns false for ${provider}`, () => {
|
|
17
|
-
assert.equal(isWorkerOnlyAgent(
|
|
22
|
+
assert.equal(isWorkerOnlyAgent(withProvider(provider)), false)
|
|
18
23
|
})
|
|
19
24
|
}
|
|
20
25
|
|
|
@@ -27,7 +32,7 @@ describe('isWorkerOnlyAgent', () => {
|
|
|
27
32
|
})
|
|
28
33
|
|
|
29
34
|
it('returns false for empty provider string', () => {
|
|
30
|
-
assert.equal(isWorkerOnlyAgent(
|
|
35
|
+
assert.equal(isWorkerOnlyAgent(withProvider('')), false)
|
|
31
36
|
})
|
|
32
37
|
})
|
|
33
38
|
|
|
@@ -3,22 +3,21 @@
|
|
|
3
3
|
*
|
|
4
4
|
* When an agent is trashed, related entities (tasks, schedules, watch jobs,
|
|
5
5
|
* connectors, webhooks, delegation jobs, chatroom memberships) must be
|
|
6
|
-
* suspended to prevent phantom daemon activity.
|
|
6
|
+
* suspended to prevent phantom daemon activity. On permanent delete the
|
|
7
7
|
* referencing rows are hard-removed.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
upsertStoredItems,
|
|
13
|
-
loadSchedules,
|
|
14
|
-
loadWatchJobs,
|
|
15
|
-
loadConnectors,
|
|
11
|
+
deleteDelegationJob,
|
|
16
12
|
loadDelegationJobs,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
} from '@/lib/server/
|
|
21
|
-
import
|
|
13
|
+
saveDelegationJobRecords,
|
|
14
|
+
} from '@/lib/server/agents/delegation-job-repository'
|
|
15
|
+
import { loadChatrooms, saveChatrooms } from '@/lib/server/chatrooms/chatroom-repository'
|
|
16
|
+
import { loadConnectors, saveConnectors } from '@/lib/server/connectors/connector-repository'
|
|
17
|
+
import { deleteWatchJob, loadWatchJobs, upsertWatchJobs } from '@/lib/server/runtime/watch-job-repository'
|
|
18
|
+
import { deleteSchedule, loadSchedules, upsertSchedules } from '@/lib/server/schedules/schedule-repository'
|
|
19
|
+
import { deleteTask, loadTasks, saveTaskMany } from '@/lib/server/tasks/task-repository'
|
|
20
|
+
import { loadWebhooks, saveWebhooks } from '@/lib/server/webhooks/webhook-repository'
|
|
22
21
|
|
|
23
22
|
interface CascadeCounts {
|
|
24
23
|
tasks: number
|
|
@@ -39,7 +38,7 @@ export function suspendAgentReferences(agentId: string): CascadeCounts {
|
|
|
39
38
|
|
|
40
39
|
// 1. Tasks — cancel active ones
|
|
41
40
|
const tasks = loadTasks()
|
|
42
|
-
const taskUpdates: Array<[string, unknown]> = []
|
|
41
|
+
const taskUpdates: Array<[string, Record<string, unknown>]> = []
|
|
43
42
|
for (const t of Object.values(tasks) as unknown as Array<Record<string, unknown>>) {
|
|
44
43
|
if (!t || t.agentId !== agentId) continue
|
|
45
44
|
const status = t.status as string | undefined
|
|
@@ -50,13 +49,13 @@ export function suspendAgentReferences(agentId: string): CascadeCounts {
|
|
|
50
49
|
}
|
|
51
50
|
}
|
|
52
51
|
if (taskUpdates.length) {
|
|
53
|
-
|
|
52
|
+
saveTaskMany(taskUpdates)
|
|
54
53
|
counts.tasks = taskUpdates.length
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
// 2. Schedules — pause (with marker for restore)
|
|
58
57
|
const schedules = loadSchedules()
|
|
59
|
-
const schedUpdates: Array<[string, unknown]> = []
|
|
58
|
+
const schedUpdates: Array<[string, Record<string, unknown>]> = []
|
|
60
59
|
for (const s of Object.values(schedules) as unknown as Array<Record<string, unknown>>) {
|
|
61
60
|
if (!s || s.agentId !== agentId) continue
|
|
62
61
|
if (s.enabled === false) continue
|
|
@@ -65,13 +64,13 @@ export function suspendAgentReferences(agentId: string): CascadeCounts {
|
|
|
65
64
|
schedUpdates.push([s.id as string, s])
|
|
66
65
|
}
|
|
67
66
|
if (schedUpdates.length) {
|
|
68
|
-
|
|
67
|
+
upsertSchedules(schedUpdates)
|
|
69
68
|
counts.schedules = schedUpdates.length
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
// 3. Watch jobs — cancel active
|
|
73
72
|
const watchJobs = loadWatchJobs()
|
|
74
|
-
const wjUpdates: Array<[string, unknown]> = []
|
|
73
|
+
const wjUpdates: Array<[string, Record<string, unknown>]> = []
|
|
75
74
|
for (const w of Object.values(watchJobs) as unknown as Array<Record<string, unknown>>) {
|
|
76
75
|
if (!w || w.agentId !== agentId) continue
|
|
77
76
|
if (w.status === 'cancelled') continue
|
|
@@ -79,26 +78,28 @@ export function suspendAgentReferences(agentId: string): CascadeCounts {
|
|
|
79
78
|
wjUpdates.push([w.id as string, w])
|
|
80
79
|
}
|
|
81
80
|
if (wjUpdates.length) {
|
|
82
|
-
|
|
81
|
+
upsertWatchJobs(wjUpdates)
|
|
83
82
|
counts.watchJobs = wjUpdates.length
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
// 4. Connectors — detach agent (keep connector alive but unrouted)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
86
|
+
{
|
|
87
|
+
const connectors = loadConnectors()
|
|
88
|
+
let connectorUpdates = 0
|
|
89
|
+
for (const c of Object.values(connectors)) {
|
|
90
|
+
if (!c || c.agentId !== agentId) continue
|
|
91
|
+
c.agentId = null
|
|
92
|
+
connectorUpdates += 1
|
|
93
|
+
}
|
|
94
|
+
if (connectorUpdates > 0) {
|
|
95
|
+
saveConnectors(connectors)
|
|
96
|
+
counts.connectors = connectorUpdates
|
|
97
|
+
}
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
// 5. Delegation jobs — cancel queued/running
|
|
100
101
|
const delegationJobs = loadDelegationJobs()
|
|
101
|
-
const djUpdates: Array<[string, unknown]> = []
|
|
102
|
+
const djUpdates: Array<[string, Record<string, unknown>]> = []
|
|
102
103
|
for (const d of Object.values(delegationJobs) as unknown as Array<Record<string, unknown>>) {
|
|
103
104
|
if (!d || d.agentId !== agentId) continue
|
|
104
105
|
const status = d.status as string | undefined
|
|
@@ -108,22 +109,22 @@ export function suspendAgentReferences(agentId: string): CascadeCounts {
|
|
|
108
109
|
}
|
|
109
110
|
}
|
|
110
111
|
if (djUpdates.length) {
|
|
111
|
-
|
|
112
|
+
saveDelegationJobRecords(djUpdates)
|
|
112
113
|
counts.delegationJobs = djUpdates.length
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
// 6. Webhooks — disable
|
|
116
117
|
const webhooks = loadWebhooks()
|
|
117
|
-
|
|
118
|
-
for (const w of Object.values(webhooks)
|
|
118
|
+
let webhookUpdates = 0
|
|
119
|
+
for (const w of Object.values(webhooks)) {
|
|
119
120
|
if (!w || w.agentId !== agentId) continue
|
|
120
121
|
if (w.enabled === false) continue
|
|
121
122
|
w.enabled = false
|
|
122
|
-
|
|
123
|
+
webhookUpdates += 1
|
|
123
124
|
}
|
|
124
|
-
if (
|
|
125
|
-
|
|
126
|
-
counts.webhooks =
|
|
125
|
+
if (webhookUpdates > 0) {
|
|
126
|
+
saveWebhooks(webhooks)
|
|
127
|
+
counts.webhooks = webhookUpdates
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
// 7. Chatrooms — remove agent from member arrays
|
|
@@ -138,23 +139,25 @@ export function suspendAgentReferences(agentId: string): CascadeCounts {
|
|
|
138
139
|
export function purgeAgentReferences(agentId: string): CascadeCounts {
|
|
139
140
|
const counts: CascadeCounts = { tasks: 0, schedules: 0, watchJobs: 0, connectors: 0, delegationJobs: 0, webhooks: 0, chatrooms: 0 }
|
|
140
141
|
|
|
141
|
-
counts.tasks = deleteMatching(
|
|
142
|
-
counts.schedules = deleteMatching(
|
|
143
|
-
counts.watchJobs = deleteMatching(
|
|
144
|
-
counts.delegationJobs = deleteMatching(
|
|
145
|
-
counts.webhooks =
|
|
142
|
+
counts.tasks = deleteMatching(loadTasks(), agentId, deleteTask)
|
|
143
|
+
counts.schedules = deleteMatching(loadSchedules(), agentId, deleteSchedule)
|
|
144
|
+
counts.watchJobs = deleteMatching(loadWatchJobs(), agentId, deleteWatchJob)
|
|
145
|
+
counts.delegationJobs = deleteMatching(loadDelegationJobs(), agentId, deleteDelegationJob)
|
|
146
|
+
counts.webhooks = purgeWebhooks(agentId)
|
|
146
147
|
|
|
147
148
|
// Connectors: detach agent but keep the connector record
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
{
|
|
150
|
+
const connectors = loadConnectors()
|
|
151
|
+
let connectorUpdates = 0
|
|
152
|
+
for (const c of Object.values(connectors)) {
|
|
153
|
+
if (!c || c.agentId !== agentId) continue
|
|
154
|
+
c.agentId = null
|
|
155
|
+
connectorUpdates += 1
|
|
156
|
+
}
|
|
157
|
+
if (connectorUpdates > 0) {
|
|
158
|
+
saveConnectors(connectors)
|
|
159
|
+
counts.connectors = connectorUpdates
|
|
160
|
+
}
|
|
158
161
|
}
|
|
159
162
|
|
|
160
163
|
counts.chatrooms = removeAgentFromChatrooms(agentId)
|
|
@@ -167,7 +170,7 @@ export function purgeAgentReferences(agentId: string): CascadeCounts {
|
|
|
167
170
|
/** Re-enable schedules that were paused by trash. */
|
|
168
171
|
export function restoreAgentSchedules(agentId: string): number {
|
|
169
172
|
const schedules = loadSchedules()
|
|
170
|
-
const updates: Array<[string, unknown]> = []
|
|
173
|
+
const updates: Array<[string, Record<string, unknown>]> = []
|
|
171
174
|
for (const s of Object.values(schedules) as unknown as Array<Record<string, unknown>>) {
|
|
172
175
|
if (!s || s.agentId !== agentId) continue
|
|
173
176
|
if (!s.suspendedByTrash) continue
|
|
@@ -176,7 +179,7 @@ export function restoreAgentSchedules(agentId: string): number {
|
|
|
176
179
|
updates.push([s.id as string, s])
|
|
177
180
|
}
|
|
178
181
|
if (updates.length) {
|
|
179
|
-
|
|
182
|
+
upsertSchedules(updates)
|
|
180
183
|
}
|
|
181
184
|
return updates.length
|
|
182
185
|
}
|
|
@@ -184,15 +187,15 @@ export function restoreAgentSchedules(agentId: string): number {
|
|
|
184
187
|
// ── Internals ───────────────────────────────────────────────────────────
|
|
185
188
|
|
|
186
189
|
function deleteMatching<T extends { agentId?: string | null; id?: string | null }>(
|
|
187
|
-
table: StorageCollection,
|
|
188
190
|
collection: Record<string, T>,
|
|
189
191
|
agentId: string,
|
|
192
|
+
deleteItem: (id: string) => void,
|
|
190
193
|
): number {
|
|
191
194
|
let count = 0
|
|
192
195
|
for (const item of Object.values(collection)) {
|
|
193
196
|
if (!item || item.agentId !== agentId) continue
|
|
194
197
|
if (!item.id) continue
|
|
195
|
-
|
|
198
|
+
deleteItem(item.id)
|
|
196
199
|
count++
|
|
197
200
|
}
|
|
198
201
|
return count
|
|
@@ -200,7 +203,7 @@ function deleteMatching<T extends { agentId?: string | null; id?: string | null
|
|
|
200
203
|
|
|
201
204
|
function removeAgentFromChatrooms(agentId: string): number {
|
|
202
205
|
const chatrooms = loadChatrooms()
|
|
203
|
-
|
|
206
|
+
let changedCount = 0
|
|
204
207
|
for (const room of Object.values(chatrooms) as unknown as Array<Record<string, unknown>>) {
|
|
205
208
|
if (!room) continue
|
|
206
209
|
let changed = false
|
|
@@ -220,10 +223,27 @@ function removeAgentFromChatrooms(agentId: string): number {
|
|
|
220
223
|
room.agentIds = agentIds.filter((id) => id !== agentId)
|
|
221
224
|
if ((room.agentIds as string[]).length !== before) changed = true
|
|
222
225
|
}
|
|
223
|
-
if (changed)
|
|
226
|
+
if (changed) changedCount += 1
|
|
224
227
|
}
|
|
225
|
-
if (
|
|
226
|
-
|
|
228
|
+
if (changedCount > 0) {
|
|
229
|
+
saveChatrooms(chatrooms)
|
|
227
230
|
}
|
|
228
|
-
return
|
|
231
|
+
return changedCount
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function purgeWebhooks(agentId: string): number {
|
|
235
|
+
const webhooks = loadWebhooks() as Record<string, Record<string, unknown>>
|
|
236
|
+
const remaining: Record<string, Record<string, unknown>> = {}
|
|
237
|
+
let count = 0
|
|
238
|
+
for (const [id, webhook] of Object.entries(webhooks)) {
|
|
239
|
+
if (webhook && webhook.agentId === agentId) {
|
|
240
|
+
count += 1
|
|
241
|
+
continue
|
|
242
|
+
}
|
|
243
|
+
remaining[id] = webhook
|
|
244
|
+
}
|
|
245
|
+
if (count > 0) {
|
|
246
|
+
saveWebhooks(remaining)
|
|
247
|
+
}
|
|
248
|
+
return count
|
|
229
249
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { loadAgents, loadTasks, loadSessions } from '@/lib/server/storage'
|
|
2
1
|
import type { Agent, BoardTask } from '@/types'
|
|
2
|
+
import { loadAgents } from '@/lib/server/agents/agent-repository'
|
|
3
|
+
import { loadSessions } from '@/lib/server/sessions/session-repository'
|
|
4
|
+
import { loadTasks } from '@/lib/server/tasks/task-repository'
|
|
3
5
|
|
|
4
6
|
export interface AgentDirectoryEntry {
|
|
5
7
|
id: string
|
|
@@ -52,19 +54,36 @@ export function getAgentDirectory(excludeId?: string): AgentDirectoryEntry[] {
|
|
|
52
54
|
return entries
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
export function buildAgentAwarenessBlock(
|
|
56
|
-
|
|
57
|
+
export function buildAgentAwarenessBlock(
|
|
58
|
+
excludeId: string,
|
|
59
|
+
opts?: {
|
|
60
|
+
delegationTargetMode?: 'all' | 'selected'
|
|
61
|
+
delegationTargetAgentIds?: string[]
|
|
62
|
+
},
|
|
63
|
+
): string {
|
|
64
|
+
let directory = getAgentDirectory(excludeId)
|
|
57
65
|
if (!directory.length) return ''
|
|
58
66
|
|
|
67
|
+
const isFiltered = opts?.delegationTargetMode === 'selected'
|
|
68
|
+
if (isFiltered) {
|
|
69
|
+
const allowedIds = new Set(opts.delegationTargetAgentIds || [])
|
|
70
|
+
directory = directory.filter((entry) => allowedIds.has(entry.id))
|
|
71
|
+
if (!directory.length) return ''
|
|
72
|
+
}
|
|
73
|
+
|
|
59
74
|
const lines = directory.map((entry) => {
|
|
60
75
|
const caps = entry.capabilities.length ? ` (${entry.capabilities.join(', ')})` : ''
|
|
61
76
|
const status = entry.statusDetail || entry.status
|
|
62
77
|
return `- **${entry.name}** [id: ${entry.id}]${caps} — ${status}`
|
|
63
78
|
})
|
|
64
79
|
|
|
80
|
+
const header = isFiltered
|
|
81
|
+
? 'These are the ONLY agents I can delegate tasks to. Do not attempt to delegate to any other agents:'
|
|
82
|
+
: 'These are the other agents I work alongside. I can hand off tasks to any of them if their skills are a better fit:'
|
|
83
|
+
|
|
65
84
|
return [
|
|
66
85
|
'## My Colleagues',
|
|
67
|
-
|
|
86
|
+
header,
|
|
68
87
|
...lines,
|
|
69
88
|
].join('\n')
|
|
70
89
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { Agent } from '@/types'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
deleteAgent as deleteStoredAgent,
|
|
5
|
+
loadAgent as loadStoredAgent,
|
|
6
|
+
loadAgents as loadStoredAgents,
|
|
7
|
+
loadTrashedAgents as loadStoredTrashedAgents,
|
|
8
|
+
patchAgent as patchStoredAgent,
|
|
9
|
+
saveAgents as saveStoredAgents,
|
|
10
|
+
upsertAgent as upsertStoredAgent,
|
|
11
|
+
} from '@/lib/server/storage'
|
|
12
|
+
import { createRecordRepository } from '@/lib/server/persistence/repository-utils'
|
|
13
|
+
|
|
14
|
+
type AgentRepositoryOptions = { includeTrashed?: boolean }
|
|
15
|
+
|
|
16
|
+
export const agentRepository = createRecordRepository<Agent, AgentRepositoryOptions>(
|
|
17
|
+
'agents',
|
|
18
|
+
{
|
|
19
|
+
get(id, options) {
|
|
20
|
+
return loadStoredAgent(id, options) as Agent | null
|
|
21
|
+
},
|
|
22
|
+
list(options) {
|
|
23
|
+
return loadStoredAgents(options) as Record<string, Agent>
|
|
24
|
+
},
|
|
25
|
+
upsert(id, value) {
|
|
26
|
+
upsertStoredAgent(id, value)
|
|
27
|
+
},
|
|
28
|
+
replace(data) {
|
|
29
|
+
saveStoredAgents(data)
|
|
30
|
+
},
|
|
31
|
+
patch(id, updater) {
|
|
32
|
+
return patchStoredAgent(id, updater as (current: Agent | null) => Agent | null) as Agent | null
|
|
33
|
+
},
|
|
34
|
+
delete(id) {
|
|
35
|
+
deleteStoredAgent(id)
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
export function getAgent(id: string, options?: AgentRepositoryOptions): Agent | null {
|
|
41
|
+
return agentRepository.get(id, options)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getAgents(ids: string[], options?: AgentRepositoryOptions): Record<string, Agent> {
|
|
45
|
+
return agentRepository.getMany(ids, options)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function listAgents(options?: AgentRepositoryOptions): Record<string, Agent> {
|
|
49
|
+
return agentRepository.list(options)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function saveAgent(id: string, agent: Agent | Record<string, unknown>): void {
|
|
53
|
+
agentRepository.upsert(id, agent as Agent)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function saveAgentMany(entries: Array<[string, Agent | Record<string, unknown>]>): void {
|
|
57
|
+
agentRepository.upsertMany(entries as Array<[string, Agent]>)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function replaceAgents(agents: Record<string, Agent | Record<string, unknown>>): void {
|
|
61
|
+
agentRepository.replace(agents as Record<string, Agent>)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function patchAgent(id: string, updater: (current: Agent | null) => Agent | null): Agent | null {
|
|
65
|
+
return agentRepository.patch(id, updater)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function deleteAgent(id: string): void {
|
|
69
|
+
agentRepository.delete(id)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function loadAgents(options?: AgentRepositoryOptions): Record<string, Agent> {
|
|
73
|
+
return listAgents(options)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function loadAgent(id: string, options?: AgentRepositoryOptions): Agent | null {
|
|
77
|
+
return getAgent(id, options)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function saveAgents(agents: Record<string, Agent | Record<string, unknown>>): void {
|
|
81
|
+
replaceAgents(agents)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function upsertAgent(id: string, agent: Agent | Record<string, unknown>): void {
|
|
85
|
+
saveAgent(id, agent)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function loadTrashedAgents(): Record<string, Agent> {
|
|
89
|
+
return loadStoredTrashedAgents() as Record<string, Agent>
|
|
90
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { DelegationJobRecord } from '@/types'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
deleteDelegationJob as deleteStoredDelegationJob,
|
|
5
|
+
loadDelegationJobItem as loadStoredDelegationJob,
|
|
6
|
+
loadDelegationJobs as loadStoredDelegationJobs,
|
|
7
|
+
patchDelegationJob as patchStoredDelegationJob,
|
|
8
|
+
upsertDelegationJob as upsertStoredDelegationJob,
|
|
9
|
+
} from '@/lib/server/storage'
|
|
10
|
+
import { createRecordRepository } from '@/lib/server/persistence/repository-utils'
|
|
11
|
+
|
|
12
|
+
export const delegationJobRepository = createRecordRepository<DelegationJobRecord>(
|
|
13
|
+
'delegation-jobs',
|
|
14
|
+
{
|
|
15
|
+
get(id) {
|
|
16
|
+
return loadStoredDelegationJob(id) as DelegationJobRecord | null
|
|
17
|
+
},
|
|
18
|
+
list() {
|
|
19
|
+
return loadStoredDelegationJobs() as Record<string, DelegationJobRecord>
|
|
20
|
+
},
|
|
21
|
+
upsert(id, value) {
|
|
22
|
+
upsertStoredDelegationJob(id, value as DelegationJobRecord)
|
|
23
|
+
},
|
|
24
|
+
patch(id, updater) {
|
|
25
|
+
return patchStoredDelegationJob(
|
|
26
|
+
id,
|
|
27
|
+
updater as (current: DelegationJobRecord | null) => DelegationJobRecord | null,
|
|
28
|
+
) as DelegationJobRecord | null
|
|
29
|
+
},
|
|
30
|
+
delete(id) {
|
|
31
|
+
deleteStoredDelegationJob(id)
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
export const getDelegationJobRecord = (id: string) => delegationJobRepository.get(id)
|
|
37
|
+
export const getDelegationJobRecords = (ids: string[]) => delegationJobRepository.getMany(ids)
|
|
38
|
+
export const listDelegationJobRecords = () => delegationJobRepository.list()
|
|
39
|
+
export const saveDelegationJobRecord = (id: string, value: DelegationJobRecord | Record<string, unknown>) =>
|
|
40
|
+
delegationJobRepository.upsert(id, value as DelegationJobRecord)
|
|
41
|
+
export const saveDelegationJobRecords = (entries: Array<[string, DelegationJobRecord | Record<string, unknown>]>) =>
|
|
42
|
+
delegationJobRepository.upsertMany(entries as Array<[string, DelegationJobRecord]>)
|
|
43
|
+
export const patchDelegationJobRecord = (
|
|
44
|
+
id: string,
|
|
45
|
+
updater: (current: DelegationJobRecord | null) => DelegationJobRecord | null,
|
|
46
|
+
) => delegationJobRepository.patch(id, updater)
|
|
47
|
+
export const deleteDelegationJobRecord = (id: string) => delegationJobRepository.delete(id)
|
|
48
|
+
|
|
49
|
+
export const loadDelegationJobs = listDelegationJobRecords
|
|
50
|
+
export const loadDelegationJob = getDelegationJobRecord
|
|
51
|
+
export const upsertDelegationJob = saveDelegationJobRecord
|
|
52
|
+
export const patchDelegationJob = patchDelegationJobRecord
|
|
53
|
+
export const deleteDelegationJob = deleteDelegationJobRecord
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { genId } from '@/lib/id'
|
|
2
2
|
import { hmrSingleton } from '@/lib/shared-utils'
|
|
3
3
|
import type { DelegationJobArtifact, DelegationJobCheckpoint, DelegationJobRecord, DelegationJobStatus } from '@/types'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
loadDelegationJob,
|
|
6
|
+
loadDelegationJobs,
|
|
7
|
+
patchDelegationJob,
|
|
8
|
+
upsertDelegationJob,
|
|
9
|
+
} from '@/lib/server/agents/delegation-job-repository'
|
|
10
|
+
import { logActivity } from '@/lib/server/activity/activity-log'
|
|
5
11
|
import { logExecution } from '@/lib/server/execution-log'
|
|
6
12
|
import { log } from '@/lib/server/logger'
|
|
7
13
|
import { debug } from '@/lib/server/debug'
|
|
8
14
|
import { createNotification } from '@/lib/server/create-notification'
|
|
9
15
|
import { enqueueSystemEvent } from '@/lib/server/runtime/system-events'
|
|
10
16
|
import { ensureDelegationMission, syncDelegationMissionFromJob } from '@/lib/server/missions/mission-service'
|
|
17
|
+
import { loadSession } from '@/lib/server/sessions/session-repository'
|
|
11
18
|
import { notify } from '@/lib/server/ws-hub'
|
|
12
19
|
|
|
13
20
|
interface DelegationRuntimeHandle {
|
|
@@ -115,7 +122,7 @@ export function createDelegationJob(input: CreateDelegationJobInput): Delegation
|
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
export function getDelegationJob(id: string): DelegationJobRecord | null {
|
|
118
|
-
const current =
|
|
125
|
+
const current = loadDelegationJob(id)
|
|
119
126
|
if (!current || typeof current !== 'object') return null
|
|
120
127
|
return current as DelegationJobRecord
|
|
121
128
|
}
|
|
@@ -144,9 +151,9 @@ export function updateDelegationJob(
|
|
|
144
151
|
}
|
|
145
152
|
})
|
|
146
153
|
if (!result) return null
|
|
147
|
-
|
|
154
|
+
syncDelegationMissionFromJob(id)
|
|
148
155
|
notifyDelegationJobsChanged()
|
|
149
|
-
return getDelegationJob(id) ||
|
|
156
|
+
return getDelegationJob(id) || result
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
export function appendDelegationCheckpoint(
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { GuardianCheckpoint } from '@/types'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
loadGuardianCheckpoints as loadStoredGuardianCheckpoints,
|
|
5
|
+
patchGuardianCheckpoint as patchStoredGuardianCheckpoint,
|
|
6
|
+
upsertGuardianCheckpoint as upsertStoredGuardianCheckpoint,
|
|
7
|
+
} from '@/lib/server/storage'
|
|
8
|
+
import { createRecordRepository } from '@/lib/server/persistence/repository-utils'
|
|
9
|
+
|
|
10
|
+
export const guardianCheckpointRepository = createRecordRepository<GuardianCheckpoint>(
|
|
11
|
+
'guardian-checkpoints',
|
|
12
|
+
{
|
|
13
|
+
get(id) {
|
|
14
|
+
return loadStoredGuardianCheckpoints()[id] || null
|
|
15
|
+
},
|
|
16
|
+
list() {
|
|
17
|
+
return loadStoredGuardianCheckpoints()
|
|
18
|
+
},
|
|
19
|
+
upsert(id, value) {
|
|
20
|
+
upsertStoredGuardianCheckpoint(id, value as GuardianCheckpoint)
|
|
21
|
+
},
|
|
22
|
+
patch(id, updater) {
|
|
23
|
+
return patchStoredGuardianCheckpoint(id, updater)
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
export const loadGuardianCheckpoints = () => guardianCheckpointRepository.list()
|
|
29
|
+
export const loadGuardianCheckpoint = (id: string) => guardianCheckpointRepository.get(id)
|
|
30
|
+
export const upsertGuardianCheckpoint = (id: string, value: GuardianCheckpoint | Record<string, unknown>) =>
|
|
31
|
+
guardianCheckpointRepository.upsert(id, value as GuardianCheckpoint)
|
|
32
|
+
export const patchGuardianCheckpoint = (
|
|
33
|
+
id: string,
|
|
34
|
+
updater: (current: GuardianCheckpoint | null) => GuardianCheckpoint | null,
|
|
35
|
+
) => guardianCheckpointRepository.patch(id, updater)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import type { ApprovalRequest, GuardianCheckpoint } from '@/types'
|
|
4
|
+
import { loadApprovals } from '@/lib/server/approvals/approval-repository'
|
|
4
5
|
import {
|
|
5
|
-
loadApprovals,
|
|
6
6
|
loadGuardianCheckpoints,
|
|
7
7
|
patchGuardianCheckpoint,
|
|
8
8
|
upsertGuardianCheckpoint,
|
|
9
|
-
} from '@/lib/server/
|
|
9
|
+
} from '@/lib/server/agents/guardian-checkpoint-repository'
|
|
10
10
|
import { requestApproval } from '@/lib/server/approvals'
|
|
11
11
|
import { errorMessage } from '@/lib/shared-utils'
|
|
12
12
|
import { genId } from '@/lib/id'
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { hmrSingleton } from '@/lib/shared-utils'
|
|
2
2
|
import type { GoalContract, Message, MessageToolEvent, Session } from '@/types'
|
|
3
3
|
import { mergeGoalContracts, parseGoalContractFromText, parseMainLoopPlan, parseMainLoopReview } from '@/lib/server/agents/autonomy-contract'
|
|
4
|
+
import {
|
|
5
|
+
deletePersistedMainLoopState,
|
|
6
|
+
loadPersistedMainLoopState,
|
|
7
|
+
upsertPersistedMainLoopState,
|
|
8
|
+
} from '@/lib/server/agents/main-loop-state-repository'
|
|
9
|
+
import { loadAgents } from '@/lib/server/agents/agent-repository'
|
|
4
10
|
import { assessAutonomyRun } from '@/lib/server/autonomy/supervisor-reflection'
|
|
5
11
|
import { enqueueSystemEvent } from '@/lib/server/runtime/system-events'
|
|
6
|
-
import { loadAgents, loadSessions, loadSettings, loadPersistedMainLoopState, upsertPersistedMainLoopState, deletePersistedMainLoopState } from '@/lib/server/storage'
|
|
7
12
|
import { buildMissionHeartbeatPrompt as buildMissionHeartbeatPromptFromMission, getMissionForSession } from '@/lib/server/missions/mission-service'
|
|
13
|
+
import { loadSettings } from '@/lib/server/settings/settings-repository'
|
|
14
|
+
import { getSession, loadSessions } from '@/lib/server/sessions/session-repository'
|
|
8
15
|
|
|
9
16
|
const LEGACY_META_LINE_RE = /\[(?:MAIN_LOOP_META|MAIN_LOOP_PLAN|MAIN_LOOP_REVIEW|AGENT_HEARTBEAT_META)\]\s*(\{[^\n]*\})?/i
|
|
10
17
|
const HEARTBEAT_META_RE = /\[AGENT_HEARTBEAT_META\]\s*(\{[^\n]*\})/i
|
|
@@ -12,7 +19,7 @@ const MAX_PENDING_EVENTS = 16
|
|
|
12
19
|
const MAX_TIMELINE_ITEMS = 40
|
|
13
20
|
const MAX_WORKING_MEMORY_NOTES = 12
|
|
14
21
|
const DEFAULT_FOLLOWUP_DELAY_MS = 1500
|
|
15
|
-
const DEFAULT_MAX_FOLLOWUP_CHAIN =
|
|
22
|
+
const DEFAULT_MAX_FOLLOWUP_CHAIN = 4
|
|
16
23
|
const MAX_LIFETIME_ITERATIONS = 200
|
|
17
24
|
|
|
18
25
|
export interface MainLoopState {
|
|
@@ -437,7 +444,7 @@ function hydrateStateFromSession(sessionId: string): MainLoopState | null {
|
|
|
437
444
|
}
|
|
438
445
|
|
|
439
446
|
function persistState(sessionId: string, state: MainLoopState): void {
|
|
440
|
-
upsertPersistedMainLoopState(sessionId, state as unknown)
|
|
447
|
+
upsertPersistedMainLoopState(sessionId, state as unknown as Record<string, unknown>)
|
|
441
448
|
}
|
|
442
449
|
|
|
443
450
|
function getOrCreateState(sessionId: string): MainLoopState | null {
|
|
@@ -738,7 +745,7 @@ export function isMainSession(session: unknown): boolean {
|
|
|
738
745
|
export function buildMainLoopHeartbeatPrompt(session: unknown, fallbackPrompt: string): string {
|
|
739
746
|
const candidate = asSession(session)
|
|
740
747
|
if (!candidate?.id) return fallbackPrompt
|
|
741
|
-
const persistedSession =
|
|
748
|
+
const persistedSession = getSession(String(candidate.id)) as Session | undefined
|
|
742
749
|
const missionPrompt = buildMissionHeartbeatPromptFromMission(
|
|
743
750
|
persistedSession || candidate as Session,
|
|
744
751
|
fallbackPrompt,
|
|
@@ -778,6 +785,7 @@ export function buildMainLoopHeartbeatPrompt(session: unknown, fallbackPrompt: s
|
|
|
778
785
|
boundedFallbackPrompt ? `Base heartbeat instructions:\n${boundedFallbackPrompt}` : '',
|
|
779
786
|
'',
|
|
780
787
|
'You are checking the durable main mission thread for this agent.',
|
|
788
|
+
'Keep this status check brief — 5-10 tool calls maximum. Read key state, summarize progress, and report. Do not attempt fixes or deep investigation during heartbeats.',
|
|
781
789
|
'Use only the current goal, plan, next action, and pending external events shown above.',
|
|
782
790
|
'Do not infer or repeat old tasks from prior heartbeats.',
|
|
783
791
|
'Prefer taking the single highest-value next step over restating the plan. Do not repeat completed work.',
|
|
@@ -1072,8 +1080,8 @@ export function handleMainLoopRunResult(input: HandleMainLoopRunResultInput): Ma
|
|
|
1072
1080
|
|| (needsReplan
|
|
1073
1081
|
? 'Replan from the latest outcome, then execute only the highest-value remaining step. Do not repeat completed work.'
|
|
1074
1082
|
: state.nextAction
|
|
1075
|
-
? `Continue
|
|
1076
|
-
:
|
|
1083
|
+
? `Continue. Next action: ${state.nextAction}. Do not repeat tool calls from previous turns.`
|
|
1084
|
+
: `Continue. You have used ${state.followupChainCount} of ${limit} followup turns. Focus on completing one concrete step, then summarize progress.`)
|
|
1077
1085
|
followup = {
|
|
1078
1086
|
message,
|
|
1079
1087
|
delayMs: DEFAULT_FOLLOWUP_DELAY_MS,
|