@swarmclawai/swarmclaw 1.2.8 → 1.2.9
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 +30 -6
- package/package.json +2 -2
- package/src/app/agents/[id]/page.tsx +1 -18
- package/src/app/api/agents/thread-route.test.ts +0 -1
- package/src/app/api/approvals/route.test.ts +6 -22
- package/src/app/api/connectors/route.ts +2 -2
- package/src/app/api/portability/export/route.ts +8 -0
- package/src/app/api/portability/import/route.test.ts +80 -0
- package/src/app/api/portability/import/route.ts +28 -0
- package/src/app/api/settings/route.ts +0 -2
- package/src/app/api/wallets/[id]/route.ts +15 -157
- package/src/app/api/wallets/generate/route.ts +22 -0
- package/src/app/api/wallets/route.test.ts +147 -0
- package/src/app/api/wallets/route.ts +13 -95
- package/src/app/autonomy/page.tsx +2 -57
- package/src/app/protocols/page.tsx +2 -21
- package/src/app/settings/page.tsx +0 -9
- package/src/app/wallets/page.tsx +105 -5
- package/src/cli/index.js +21 -33
- package/src/cli/spec.js +19 -30
- package/src/components/agents/agent-sheet.tsx +2 -40
- package/src/components/agents/inspector-panel.tsx +0 -83
- package/src/components/chat/chat-card.tsx +0 -31
- package/src/components/chat/message-bubble.tsx +1 -108
- package/src/components/connectors/connector-sheet.tsx +25 -1
- package/src/components/layout/sidebar-rail.tsx +6 -10
- package/src/components/projects/project-detail.tsx +3 -35
- package/src/components/projects/tabs/overview-tab.tsx +3 -59
- package/src/components/projects/tabs/work-tab.tsx +7 -77
- package/src/components/protocols/structured-session-launcher.tsx +1 -22
- package/src/components/shared/connector-platform-icon.tsx +1 -0
- package/src/components/tasks/task-card.tsx +4 -34
- package/src/components/tasks/task-sheet.tsx +6 -36
- package/src/components/wallets/wallet-list.tsx +150 -0
- package/src/lib/app/navigation.test.ts +0 -13
- package/src/lib/app/navigation.ts +2 -7
- package/src/lib/app/view-constants.ts +14 -19
- package/src/lib/server/agents/agent-thread-session.ts +0 -1
- package/src/lib/server/agents/delegation-advisory.test.ts +0 -1
- package/src/lib/server/agents/delegation-jobs.test.ts +0 -69
- package/src/lib/server/agents/delegation-jobs.ts +0 -25
- package/src/lib/server/agents/main-agent-loop.ts +1 -49
- package/src/lib/server/agents/subagent-runtime.ts +0 -1
- package/src/lib/server/approval-match.ts +0 -85
- package/src/lib/server/approvals.test.ts +6 -6
- package/src/lib/server/approvals.ts +0 -6
- package/src/lib/server/autonomy/supervisor-reflection.test.ts +0 -1
- package/src/lib/server/builtin-extensions.ts +0 -2
- package/src/lib/server/capability-router.test.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +14 -14
- package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-utils.ts +0 -2
- package/src/lib/server/chat-execution/chat-streaming-utils.ts +2 -30
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +1 -36
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +2 -22
- package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
- package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
- package/src/lib/server/chat-execution/message-classifier.ts +1 -16
- package/src/lib/server/chat-execution/prompt-builder.test.ts +0 -1
- package/src/lib/server/chat-execution/prompt-builder.ts +0 -30
- package/src/lib/server/chat-execution/prompt-sections.ts +0 -1
- package/src/lib/server/chat-execution/situational-awareness.test.ts +2 -73
- package/src/lib/server/chat-execution/situational-awareness.ts +4 -38
- package/src/lib/server/chat-execution/stream-agent-chat.test.ts +8 -123
- package/src/lib/server/chat-execution/stream-agent-chat.ts +1 -5
- package/src/lib/server/chat-execution/stream-continuation.test.ts +4 -52
- package/src/lib/server/chat-execution/stream-continuation.ts +6 -48
- package/src/lib/server/chatrooms/session-mailbox.ts +0 -10
- package/src/lib/server/chats/chat-session-service.ts +3 -5
- package/src/lib/server/connectors/connector-inbound.ts +0 -1
- package/src/lib/server/connectors/connector-lifecycle.ts +19 -3
- package/src/lib/server/connectors/connector-service.ts +39 -9
- package/src/lib/server/connectors/swarmdock-bidding.ts +74 -0
- package/src/lib/server/connectors/swarmdock-payloads.test.ts +85 -0
- package/src/lib/server/connectors/swarmdock-secret.test.ts +128 -0
- package/src/lib/server/connectors/swarmdock-secret.ts +152 -0
- package/src/lib/server/connectors/swarmdock-tasks.ts +119 -0
- package/src/lib/server/connectors/swarmdock.ts +255 -0
- package/src/lib/server/execution-brief.test.ts +2 -25
- package/src/lib/server/execution-brief.ts +12 -35
- package/src/lib/server/execution-engine/task-attempt.ts +0 -1
- package/src/lib/server/persistence/storage-context.ts +0 -5
- package/src/lib/server/portability/export.ts +109 -0
- package/src/lib/server/portability/import.ts +159 -0
- package/src/lib/server/protocols/protocol-normalization.ts +0 -4
- package/src/lib/server/protocols/protocol-queries.ts +0 -6
- package/src/lib/server/protocols/protocol-run-lifecycle.ts +4 -32
- package/src/lib/server/protocols/protocol-service.ts +0 -1
- package/src/lib/server/protocols/protocol-step-helpers.ts +0 -4
- package/src/lib/server/protocols/protocol-step-processors.ts +0 -6
- package/src/lib/server/protocols/protocol-swarm.ts +0 -2
- package/src/lib/server/protocols/protocol-types.ts +0 -2
- package/src/lib/server/provider-health.ts +0 -9
- package/src/lib/server/runtime/daemon-state/core.ts +0 -9
- package/src/lib/server/runtime/daemon-state.test.ts +0 -35
- package/src/lib/server/runtime/heartbeat-service.ts +3 -23
- package/src/lib/server/runtime/queue/core.ts +11 -33
- package/src/lib/server/runtime/runtime-storage-write-paths.test.ts +6 -6
- package/src/lib/server/runtime/scheduler.ts +0 -13
- package/src/lib/server/runtime/session-run-manager/drain.ts +0 -24
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +0 -1
- package/src/lib/server/runtime/session-run-manager/queries.ts +0 -1
- package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
- package/src/lib/server/runtime/session-run-manager.test.ts +0 -28
- package/src/lib/server/session-tools/crud.ts +0 -14
- package/src/lib/server/session-tools/delegate.ts +0 -4
- package/src/lib/server/session-tools/index.ts +0 -4
- package/src/lib/server/session-tools/team-context.ts +0 -3
- package/src/lib/server/storage-normalization.ts +8 -0
- package/src/lib/server/storage.ts +18 -45
- package/src/lib/server/tasks/task-checkout.ts +59 -0
- package/src/lib/server/tasks/task-lifecycle.ts +2 -0
- package/src/lib/server/tasks/task-route-service.ts +4 -26
- package/src/lib/server/tasks/task-service.ts +0 -7
- package/src/lib/server/tool-aliases.ts +0 -1
- package/src/lib/server/tool-capability-policy-advanced.test.ts +4 -4
- package/src/lib/server/tool-capability-policy.ts +0 -2
- package/src/lib/server/tool-planning.ts +0 -12
- package/src/lib/server/universal-tool-access.ts +0 -1
- package/src/lib/server/wallets/wallet-crypto.ts +33 -0
- package/src/lib/server/wallets/wallet-repository.ts +24 -0
- package/src/lib/server/wallets/wallet-service.ts +119 -0
- package/src/lib/server/working-state/extraction.ts +8 -42
- package/src/lib/server/working-state/normalization.ts +10 -103
- package/src/lib/server/working-state/service.ts +12 -21
- package/src/lib/strip-internal-metadata.test.ts +1 -1
- package/src/lib/strip-internal-metadata.ts +1 -1
- package/src/lib/tool-definitions.ts +0 -1
- package/src/lib/validation/schemas.ts +33 -2
- package/src/stores/slices/data-slice.ts +5 -1
- package/src/stores/slices/ui-slice.ts +0 -4
- package/src/types/agent.ts +0 -84
- package/src/types/app-settings.ts +0 -2
- package/src/types/approval.ts +0 -2
- package/src/types/connector.ts +1 -0
- package/src/types/index.ts +1 -1
- package/src/types/message.ts +0 -1
- package/src/types/misc.ts +0 -2
- package/src/types/protocol.ts +0 -2
- package/src/types/run.ts +0 -3
- package/src/types/session.ts +1 -51
- package/src/types/swarmdock.ts +29 -0
- package/src/types/task.ts +7 -3
- package/src/types/working-state.ts +2 -9
- package/src/views/settings/section-runtime-loop.tsx +0 -14
- package/src/app/api/canvas/[sessionId]/route.ts +0 -35
- package/src/app/api/missions/[id]/actions/route.ts +0 -31
- package/src/app/api/missions/[id]/events/route.ts +0 -14
- package/src/app/api/missions/[id]/route.ts +0 -10
- package/src/app/api/missions/route.test.ts +0 -244
- package/src/app/api/missions/route.ts +0 -57
- package/src/app/api/wallets/[id]/approve/route.ts +0 -79
- package/src/app/api/wallets/[id]/balance-history/route.ts +0 -18
- package/src/app/api/wallets/[id]/send/route.ts +0 -113
- package/src/app/api/wallets/[id]/transactions/route.ts +0 -18
- package/src/app/missions/[id]/page.tsx +0 -3
- package/src/app/missions/page.tsx +0 -685
- package/src/components/canvas/canvas-panel.tsx +0 -267
- package/src/components/wallets/wallet-approval-dialog.tsx +0 -107
- package/src/components/wallets/wallet-panel.tsx +0 -1010
- package/src/components/wallets/wallet-section.tsx +0 -260
- package/src/features/missions/queries.ts +0 -23
- package/src/lib/canvas-content.test.ts +0 -360
- package/src/lib/canvas-content.ts +0 -198
- package/src/lib/server/canvas-content.test.ts +0 -32
- package/src/lib/server/canvas-content.ts +0 -6
- package/src/lib/server/ethereum.ts +0 -591
- package/src/lib/server/evm-swap.ts +0 -476
- package/src/lib/server/missions/mission-intent.test.ts +0 -63
- package/src/lib/server/missions/mission-intent.ts +0 -569
- package/src/lib/server/missions/mission-repository.ts +0 -74
- package/src/lib/server/missions/mission-service/actions.ts +0 -6
- package/src/lib/server/missions/mission-service/bindings.ts +0 -9
- package/src/lib/server/missions/mission-service/context.ts +0 -4
- package/src/lib/server/missions/mission-service/core.ts +0 -2271
- package/src/lib/server/missions/mission-service/queries.ts +0 -12
- package/src/lib/server/missions/mission-service/recovery.ts +0 -5
- package/src/lib/server/missions/mission-service/ticks.ts +0 -9
- package/src/lib/server/missions/mission-service.test.ts +0 -888
- package/src/lib/server/missions/mission-service.ts +0 -6
- package/src/lib/server/session-tools/canvas.ts +0 -105
- package/src/lib/server/session-tools/wallet-tool.test.ts +0 -150
- package/src/lib/server/session-tools/wallet.ts +0 -1287
- package/src/lib/server/solana.ts +0 -327
- package/src/lib/server/wallet/wallet-execution.test.ts +0 -198
- package/src/lib/server/wallet/wallet-portfolio.test.ts +0 -98
- package/src/lib/server/wallet/wallet-portfolio.ts +0 -772
- package/src/lib/server/wallet/wallet-service.test.ts +0 -81
- package/src/lib/server/wallet/wallet-service.ts +0 -225
- package/src/lib/wallet/wallet-transactions.test.ts +0 -75
- package/src/lib/wallet/wallet-transactions.ts +0 -43
- package/src/lib/wallet/wallet.test.ts +0 -333
- package/src/lib/wallet/wallet.ts +0 -183
- package/src/types/mission.ts +0 -185
- package/src/views/settings/section-wallets.tsx +0 -35
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react'
|
|
4
|
+
import { useAppStore } from '@/stores/use-app-store'
|
|
5
|
+
import { AgentAvatar } from '@/components/agents/agent-avatar'
|
|
6
|
+
import { api } from '@/lib/app/api-client'
|
|
7
|
+
|
|
8
|
+
export function WalletList() {
|
|
9
|
+
const wallets = useAppStore((s) => s.wallets)
|
|
10
|
+
const loadWallets = useAppStore((s) => s.loadWallets)
|
|
11
|
+
const agents = useAppStore((s) => s.agents)
|
|
12
|
+
const [copiedId, setCopiedId] = useState<string | null>(null)
|
|
13
|
+
const [deletingId, setDeletingId] = useState<string | null>(null)
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
loadWallets()
|
|
17
|
+
}, [loadWallets])
|
|
18
|
+
|
|
19
|
+
const handleCopy = async (e: React.MouseEvent, address: string, walletId: string) => {
|
|
20
|
+
e.stopPropagation()
|
|
21
|
+
await navigator.clipboard.writeText(address)
|
|
22
|
+
setCopiedId(walletId)
|
|
23
|
+
setTimeout(() => setCopiedId(null), 2000)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const handleDelete = async (e: React.MouseEvent, id: string) => {
|
|
27
|
+
e.stopPropagation()
|
|
28
|
+
if (deletingId === id) {
|
|
29
|
+
await api('DELETE', `/wallets/${id}`)
|
|
30
|
+
setDeletingId(null)
|
|
31
|
+
loadWallets()
|
|
32
|
+
} else {
|
|
33
|
+
setDeletingId(id)
|
|
34
|
+
setTimeout(() => setDeletingId(null), 3000)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const truncateAddress = (addr: string) =>
|
|
39
|
+
addr.length > 12 ? `${addr.slice(0, 6)}...${addr.slice(-4)}` : addr
|
|
40
|
+
|
|
41
|
+
const walletList = Object.values(wallets)
|
|
42
|
+
|
|
43
|
+
if (!walletList.length) {
|
|
44
|
+
return (
|
|
45
|
+
<div className="flex-1 flex flex-col items-center justify-center px-6 py-12 text-center">
|
|
46
|
+
<div className="w-12 h-12 rounded-[14px] bg-white/[0.03] border border-white/[0.06] flex items-center justify-center mb-4">
|
|
47
|
+
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" className="text-text-3">
|
|
48
|
+
<rect x="2" y="6" width="20" height="14" rx="2" /><path d="M22 10H18a2 2 0 0 0 0 4h4" /><path d="M6 6V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2" />
|
|
49
|
+
</svg>
|
|
50
|
+
</div>
|
|
51
|
+
<p className="text-[13px] text-text-3 mb-1 font-600">No wallets yet</p>
|
|
52
|
+
<p className="text-[12px] text-text-3/60">Generate a wallet for your agents to transact on Base L2</p>
|
|
53
|
+
</div>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div className="flex-1 overflow-y-auto px-5 pb-6">
|
|
59
|
+
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-3">
|
|
60
|
+
{walletList.map((wallet, idx) => {
|
|
61
|
+
const agent = agents[wallet.agentId]
|
|
62
|
+
return (
|
|
63
|
+
<div
|
|
64
|
+
key={wallet.id}
|
|
65
|
+
className="w-full text-left p-4 rounded-[14px] bg-surface border border-white/[0.06]
|
|
66
|
+
hover:border-white/[0.12] hover:bg-white/[0.02] transition-all group"
|
|
67
|
+
style={{
|
|
68
|
+
fontFamily: 'inherit',
|
|
69
|
+
animation: 'spring-in 0.5s var(--ease-spring) both',
|
|
70
|
+
animationDelay: `${idx * 0.05}s`,
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
{/* Header: agent + delete */}
|
|
74
|
+
<div className="flex items-center gap-2.5 mb-2">
|
|
75
|
+
{agent ? (
|
|
76
|
+
<AgentAvatar seed={agent.avatarSeed} avatarUrl={agent.avatarUrl} name={agent.name} size={20} />
|
|
77
|
+
) : (
|
|
78
|
+
<div className="w-5 h-5 rounded-full bg-white/[0.06]" />
|
|
79
|
+
)}
|
|
80
|
+
<span className="text-[13px] font-600 text-text truncate flex-1">
|
|
81
|
+
{agent?.name || 'Unknown Agent'}
|
|
82
|
+
</span>
|
|
83
|
+
<button
|
|
84
|
+
onClick={(e) => handleDelete(e, wallet.id)}
|
|
85
|
+
className={`text-[10px] font-600 px-1.5 py-0.5 rounded-[6px] transition-colors cursor-pointer ${
|
|
86
|
+
deletingId === wallet.id
|
|
87
|
+
? 'text-red-400 bg-red-400/10'
|
|
88
|
+
: 'text-text-3/40 hover:text-red-400'
|
|
89
|
+
}`}
|
|
90
|
+
title={deletingId === wallet.id ? 'Click again to confirm' : 'Delete wallet'}
|
|
91
|
+
>
|
|
92
|
+
{deletingId === wallet.id ? 'Confirm?' : (
|
|
93
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
94
|
+
<path d="M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
|
95
|
+
</svg>
|
|
96
|
+
)}
|
|
97
|
+
</button>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
{/* Address row */}
|
|
101
|
+
<div className="flex items-center gap-2 mb-2">
|
|
102
|
+
<span className="text-[12px] font-mono text-text-3 truncate">{truncateAddress(wallet.walletAddress)}</span>
|
|
103
|
+
<button
|
|
104
|
+
onClick={(e) => handleCopy(e, wallet.walletAddress, wallet.id)}
|
|
105
|
+
className="text-text-3/40 hover:text-text-2 transition-colors shrink-0 cursor-pointer"
|
|
106
|
+
title="Copy address"
|
|
107
|
+
>
|
|
108
|
+
{copiedId === wallet.id ? (
|
|
109
|
+
<span className="text-[10px] font-600 text-emerald-400">Copied!</span>
|
|
110
|
+
) : (
|
|
111
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
|
112
|
+
<rect x="9" y="9" width="13" height="13" rx="2" /><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
|
|
113
|
+
</svg>
|
|
114
|
+
)}
|
|
115
|
+
</button>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
{/* Badges row */}
|
|
119
|
+
<div className="flex items-center gap-2 flex-wrap">
|
|
120
|
+
<span className="text-[10px] font-600 px-1.5 py-0.5 rounded-[6px] bg-blue-500/10 text-blue-400">
|
|
121
|
+
Base L2
|
|
122
|
+
</span>
|
|
123
|
+
{wallet.requireApproval && (
|
|
124
|
+
<span className="text-[10px] font-600 px-1.5 py-0.5 rounded-[6px] bg-amber-500/10 text-amber-400">
|
|
125
|
+
Approval Required
|
|
126
|
+
</span>
|
|
127
|
+
)}
|
|
128
|
+
{wallet.spendingLimitUsdc && (
|
|
129
|
+
<span className="text-[10px] font-600 text-text-3/60">
|
|
130
|
+
Limit: ${wallet.spendingLimitUsdc} USDC
|
|
131
|
+
</span>
|
|
132
|
+
)}
|
|
133
|
+
{wallet.dailyLimitUsdc && (
|
|
134
|
+
<span className="text-[10px] font-600 text-text-3/60">
|
|
135
|
+
Daily: ${wallet.dailyLimitUsdc} USDC
|
|
136
|
+
</span>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
{/* Label */}
|
|
141
|
+
{wallet.label && (
|
|
142
|
+
<div className="mt-2 text-[11px] text-text-3/60 truncate">{wallet.label}</div>
|
|
143
|
+
)}
|
|
144
|
+
</div>
|
|
145
|
+
)
|
|
146
|
+
})}
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
@@ -39,19 +39,6 @@ describe('getViewPath', () => {
|
|
|
39
39
|
})
|
|
40
40
|
})
|
|
41
41
|
|
|
42
|
-
describe('getMissionPath', () => {
|
|
43
|
-
it('returns /missions when no ID is provided', () => {
|
|
44
|
-
assert.equal(mod.getMissionPath(), '/missions')
|
|
45
|
-
assert.equal(mod.getMissionPath(null), '/missions')
|
|
46
|
-
assert.equal(mod.getMissionPath(''), '/missions')
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('returns /missions/{encoded} with an ID', () => {
|
|
50
|
-
assert.equal(mod.getMissionPath('m-42'), '/missions/m-42')
|
|
51
|
-
assert.equal(mod.getMissionPath('has/slash'), '/missions/has%2Fslash')
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
|
|
55
42
|
describe('pathToView', () => {
|
|
56
43
|
it('matches exact path', () => {
|
|
57
44
|
assert.equal(mod.pathToView('/agents'), 'agents')
|
|
@@ -13,9 +13,10 @@ const VIEW_TO_PATH: Record<AppView, string> = {
|
|
|
13
13
|
protocols: '/protocols',
|
|
14
14
|
schedules: '/schedules',
|
|
15
15
|
memory: '/memory',
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
tasks: '/tasks',
|
|
18
18
|
secrets: '/secrets',
|
|
19
|
+
wallets: '/wallets',
|
|
19
20
|
providers: '/providers',
|
|
20
21
|
skills: '/skills',
|
|
21
22
|
connectors: '/connectors',
|
|
@@ -25,7 +26,6 @@ const VIEW_TO_PATH: Record<AppView, string> = {
|
|
|
25
26
|
logs: '/logs',
|
|
26
27
|
extensions: '/extensions',
|
|
27
28
|
usage: '/usage',
|
|
28
|
-
wallets: '/wallets',
|
|
29
29
|
runs: '/runs',
|
|
30
30
|
autonomy: '/autonomy',
|
|
31
31
|
settings: '/settings',
|
|
@@ -42,11 +42,6 @@ export function getViewPath(view: AppView, id?: string | null): string {
|
|
|
42
42
|
return base
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export function getMissionPath(missionId?: string | null): string {
|
|
46
|
-
if (!missionId) return VIEW_TO_PATH.missions
|
|
47
|
-
return `${VIEW_TO_PATH.missions}/${encodeURIComponent(missionId)}`
|
|
48
|
-
}
|
|
49
|
-
|
|
50
45
|
/** Map a pathname back to an AppView. Returns null for unknown paths. */
|
|
51
46
|
export function pathToView(pathname: string): AppView | null {
|
|
52
47
|
for (const [view, path] of Object.entries(VIEW_TO_PATH)) {
|
|
@@ -9,9 +9,10 @@ export const VIEW_LABELS: Record<AppView, string> = {
|
|
|
9
9
|
protocols: 'Sessions',
|
|
10
10
|
schedules: 'Schedules',
|
|
11
11
|
memory: 'Memory',
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
tasks: 'Tasks',
|
|
14
14
|
secrets: 'Secrets',
|
|
15
|
+
wallets: 'Wallets',
|
|
15
16
|
providers: 'Providers',
|
|
16
17
|
skills: 'Skills',
|
|
17
18
|
connectors: 'Connectors',
|
|
@@ -21,7 +22,6 @@ export const VIEW_LABELS: Record<AppView, string> = {
|
|
|
21
22
|
logs: 'Logs',
|
|
22
23
|
extensions: 'Extensions',
|
|
23
24
|
usage: 'Usage',
|
|
24
|
-
wallets: 'Wallets',
|
|
25
25
|
runs: 'Runs',
|
|
26
26
|
autonomy: 'Autonomy',
|
|
27
27
|
settings: 'Settings',
|
|
@@ -53,9 +53,10 @@ export const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
53
53
|
protocols: 'Temporary structured sessions and protocol-driven runs',
|
|
54
54
|
schedules: 'Automated task schedules',
|
|
55
55
|
memory: 'Long-term agent memory store',
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
tasks: 'Task board for agent work and queued runs',
|
|
58
58
|
secrets: 'API keys, tokens, and encrypted credentials',
|
|
59
|
+
wallets: 'Crypto wallets for agent-initiated on-chain transactions',
|
|
59
60
|
providers: 'LLM providers & custom endpoints',
|
|
60
61
|
skills: 'Reusable instruction sets for agents',
|
|
61
62
|
connectors: 'Chat platform bridges (Discord, Slack, etc.)',
|
|
@@ -65,7 +66,6 @@ export const VIEW_DESCRIPTIONS: Record<AppView, string> = {
|
|
|
65
66
|
logs: 'Application logs & error tracking',
|
|
66
67
|
extensions: 'Manage external extensions and marketplace installs',
|
|
67
68
|
usage: 'Usage metrics, cost tracking & agent performance',
|
|
68
|
-
wallets: 'Agent crypto wallets — hold funds, send SOL, manage spending',
|
|
69
69
|
runs: 'Live run monitoring & history',
|
|
70
70
|
autonomy: 'Estops, incidents, and runtime autonomy controls',
|
|
71
71
|
settings: 'Manage defaults, providers, secrets, and automation settings',
|
|
@@ -89,7 +89,7 @@ export const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { ic
|
|
|
89
89
|
protocols: {
|
|
90
90
|
icon: 'list',
|
|
91
91
|
title: 'Structured Sessions',
|
|
92
|
-
description: 'Run temporary bounded sessions from chats, chatrooms, tasks,
|
|
92
|
+
description: 'Run temporary bounded sessions from chats, chatrooms, tasks, or schedules without turning every surface into a workflow engine.',
|
|
93
93
|
features: ['Start one-agent or multi-agent structured sessions from context', 'Use neutral built-in templates like review, discussion, and decision rounds', 'Keep a hidden transcript plus durable run events', 'Archive the outcome and post a compact summary back when needed'],
|
|
94
94
|
},
|
|
95
95
|
schedules: {
|
|
@@ -104,12 +104,7 @@ export const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { ic
|
|
|
104
104
|
description: 'Long-term memory store for AI agents so they can retain useful context across conversations.',
|
|
105
105
|
features: ['Agents store findings and learnings automatically', 'Full-text search across all stored memories', 'Organized by categories and agents', 'Persists across conversations for continuity'],
|
|
106
106
|
},
|
|
107
|
-
|
|
108
|
-
icon: 'target',
|
|
109
|
-
title: 'Missions',
|
|
110
|
-
description: 'Track durable objectives, blockers, waits, verification, and linked work across chats, schedules, and delegation.',
|
|
111
|
-
features: ['Inspect active and waiting missions', 'Review child missions and linked tasks', 'Understand why a mission is blocked or complete', 'Resume, replan, or retry verification from one place'],
|
|
112
|
-
},
|
|
107
|
+
|
|
113
108
|
tasks: {
|
|
114
109
|
icon: 'clipboard',
|
|
115
110
|
title: 'Task Board',
|
|
@@ -122,6 +117,12 @@ export const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { ic
|
|
|
122
117
|
description: 'Manage API keys and credentials that agents and integrations can access securely.',
|
|
123
118
|
features: ['Store keys for external services (Gmail, APIs, etc.)', 'Scope secrets globally or to specific agents', 'Encrypted at rest with AES-256-GCM', 'Agents retrieve secrets through configured tools'],
|
|
124
119
|
},
|
|
120
|
+
wallets: {
|
|
121
|
+
icon: 'wallet',
|
|
122
|
+
title: 'Wallets',
|
|
123
|
+
description: 'Manage crypto wallets that agents use for on-chain transactions and payments.',
|
|
124
|
+
features: ['Generate wallets with encrypted private keys', 'Assign wallets to specific agents', 'Set spending and daily USDC limits', 'Require human approval for transactions'],
|
|
125
|
+
},
|
|
125
126
|
providers: {
|
|
126
127
|
icon: 'zap',
|
|
127
128
|
title: 'Providers',
|
|
@@ -212,16 +213,10 @@ export const VIEW_EMPTY_STATES: Record<Exclude<AppView, 'agents' | 'home'>, { ic
|
|
|
212
213
|
description: 'Audit trail of all entity mutations across the system.',
|
|
213
214
|
features: ['Track agent, task, and connector changes', 'Filter by entity type and action', 'Real-time updates via WebSocket', 'Relative timestamps'],
|
|
214
215
|
},
|
|
215
|
-
wallets: {
|
|
216
|
-
icon: 'wallet',
|
|
217
|
-
title: 'Wallets',
|
|
218
|
-
description: 'Agent crypto wallets for autonomous financial operations on Solana.',
|
|
219
|
-
features: ['Create Solana wallets for agents', 'Per-transaction and daily spending limits', 'User approval for transactions', 'Balance tracking and transaction history'],
|
|
220
|
-
},
|
|
221
216
|
}
|
|
222
217
|
|
|
223
218
|
export const FULL_WIDTH_VIEWS = new Set<AppView>([
|
|
224
|
-
'home', 'org_chart', 'inbox', 'chatrooms', 'protocols', 'schedules', '
|
|
219
|
+
'home', 'org_chart', 'inbox', 'chatrooms', 'protocols', 'schedules', 'secrets', 'wallets', 'providers', 'skills',
|
|
225
220
|
'connectors', 'webhooks', 'mcp_servers', 'knowledge', 'extensions',
|
|
226
|
-
'usage', '
|
|
221
|
+
'usage', 'runs', 'autonomy', 'logs', 'settings', 'activity', 'projects',
|
|
227
222
|
])
|
|
@@ -89,7 +89,6 @@ function buildThreadSession(agent: Agent, sessionId: string, user: string, creat
|
|
|
89
89
|
vibe: existing?.vibe,
|
|
90
90
|
theme: existing?.theme,
|
|
91
91
|
avatar: existing?.avatar,
|
|
92
|
-
canvasContent: existing?.canvasContent || null,
|
|
93
92
|
}
|
|
94
93
|
return applyResolvedRoute(
|
|
95
94
|
baseSession,
|
|
@@ -62,7 +62,6 @@ function makeClassification(overrides: Partial<MessageClassification>): MessageC
|
|
|
62
62
|
taskIntent: 'general',
|
|
63
63
|
isDeliverableTask: false,
|
|
64
64
|
isBroadGoal: false,
|
|
65
|
-
walletIntent: 'none',
|
|
66
65
|
hasHumanSignals: false,
|
|
67
66
|
hasSignificantEvent: false,
|
|
68
67
|
isResearchSynthesis: false,
|
|
@@ -225,73 +225,4 @@ describe('delegation-jobs', () => {
|
|
|
225
225
|
)
|
|
226
226
|
})
|
|
227
227
|
|
|
228
|
-
it('creates and syncs a child mission for delegation jobs', async () => {
|
|
229
|
-
const storage = await import('@/lib/server/storage')
|
|
230
|
-
const missions = await import('@/lib/server/missions/mission-service')
|
|
231
|
-
|
|
232
|
-
storage.saveSessions({
|
|
233
|
-
'mission-parent-session': {
|
|
234
|
-
id: 'mission-parent-session',
|
|
235
|
-
name: 'Parent Session',
|
|
236
|
-
cwd: process.cwd(),
|
|
237
|
-
user: 'tester',
|
|
238
|
-
provider: 'ollama',
|
|
239
|
-
model: 'test-model',
|
|
240
|
-
messages: [],
|
|
241
|
-
createdAt: Date.now(),
|
|
242
|
-
lastActiveAt: Date.now(),
|
|
243
|
-
agentId: 'agent-parent',
|
|
244
|
-
},
|
|
245
|
-
})
|
|
246
|
-
storage.saveAgents({
|
|
247
|
-
'agent-parent': {
|
|
248
|
-
id: 'agent-parent',
|
|
249
|
-
name: 'Parent Agent',
|
|
250
|
-
provider: 'ollama',
|
|
251
|
-
model: 'test-model',
|
|
252
|
-
systemPrompt: 'test',
|
|
253
|
-
},
|
|
254
|
-
'agent-child': {
|
|
255
|
-
id: 'agent-child',
|
|
256
|
-
name: 'Child Agent',
|
|
257
|
-
provider: 'ollama',
|
|
258
|
-
model: 'test-model',
|
|
259
|
-
systemPrompt: 'test',
|
|
260
|
-
},
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
const parentMission = await missions.resolveMissionForTurn({
|
|
264
|
-
session: storage.loadSessions()['mission-parent-session'],
|
|
265
|
-
message: 'Build the release pipeline and delegate the test matrix.',
|
|
266
|
-
source: 'chat',
|
|
267
|
-
internal: false,
|
|
268
|
-
runId: 'run-parent',
|
|
269
|
-
generateText: async () => JSON.stringify({
|
|
270
|
-
action: 'create_new',
|
|
271
|
-
objective: 'Build the release pipeline',
|
|
272
|
-
successCriteria: ['delegated matrix completes'],
|
|
273
|
-
currentStep: 'Delegate the test matrix',
|
|
274
|
-
}),
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
const job = delegationJobs.createDelegationJob({
|
|
278
|
-
kind: 'subagent',
|
|
279
|
-
parentSessionId: 'mission-parent-session',
|
|
280
|
-
parentMissionId: parentMission?.id || null,
|
|
281
|
-
childSessionId: 'child-session-1',
|
|
282
|
-
agentId: 'agent-child',
|
|
283
|
-
task: 'Run the test matrix',
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
const started = delegationJobs.startDelegationJob(job.id, { childSessionId: 'child-session-1' })
|
|
287
|
-
const completed = delegationJobs.completeDelegationJob(job.id, 'Matrix passed')
|
|
288
|
-
const childMission = completed?.missionId ? missions.loadMissionById(completed.missionId) : null
|
|
289
|
-
const refreshedParent = parentMission?.id ? missions.loadMissionById(parentMission.id) : null
|
|
290
|
-
|
|
291
|
-
assert.ok(started?.missionId)
|
|
292
|
-
assert.equal(started?.parentMissionId, parentMission?.id || null)
|
|
293
|
-
assert.equal(childMission?.parentMissionId, parentMission?.id || null)
|
|
294
|
-
assert.equal(childMission?.status, 'completed')
|
|
295
|
-
assert.ok(refreshedParent?.childMissionIds?.includes(childMission?.id || ''))
|
|
296
|
-
})
|
|
297
228
|
})
|
|
@@ -13,8 +13,6 @@ import { log } from '@/lib/server/logger'
|
|
|
13
13
|
import { debug } from '@/lib/server/debug'
|
|
14
14
|
import { createNotification } from '@/lib/server/create-notification'
|
|
15
15
|
import { enqueueSystemEvent } from '@/lib/server/runtime/system-events'
|
|
16
|
-
import { ensureDelegationMission, syncDelegationMissionFromJob } from '@/lib/server/missions/mission-service'
|
|
17
|
-
import { loadSession } from '@/lib/server/sessions/session-repository'
|
|
18
16
|
import { notify } from '@/lib/server/ws-hub'
|
|
19
17
|
|
|
20
18
|
interface DelegationRuntimeHandle {
|
|
@@ -42,8 +40,6 @@ export interface CreateDelegationJobInput {
|
|
|
42
40
|
kind: DelegationJobRecord['kind']
|
|
43
41
|
task: string
|
|
44
42
|
backend?: DelegationJobRecord['backend']
|
|
45
|
-
missionId?: string | null
|
|
46
|
-
parentMissionId?: string | null
|
|
47
43
|
parentSessionId?: string | null
|
|
48
44
|
childSessionId?: string | null
|
|
49
45
|
agentId?: string | null
|
|
@@ -53,15 +49,11 @@ export interface CreateDelegationJobInput {
|
|
|
53
49
|
|
|
54
50
|
export function createDelegationJob(input: CreateDelegationJobInput): DelegationJobRecord {
|
|
55
51
|
const createdAt = Date.now()
|
|
56
|
-
const inferredParentMissionId = input.parentMissionId
|
|
57
|
-
|| (input.parentSessionId ? loadSession(input.parentSessionId)?.missionId || null : null)
|
|
58
52
|
const job: DelegationJobRecord = {
|
|
59
53
|
id: genId(10),
|
|
60
54
|
kind: input.kind,
|
|
61
55
|
status: 'queued',
|
|
62
56
|
backend: input.backend ?? null,
|
|
63
|
-
missionId: input.missionId ?? null,
|
|
64
|
-
parentMissionId: inferredParentMissionId,
|
|
65
57
|
parentSessionId: input.parentSessionId ?? null,
|
|
66
58
|
childSessionId: input.childSessionId ?? null,
|
|
67
59
|
agentId: input.agentId ?? null,
|
|
@@ -85,22 +77,6 @@ export function createDelegationJob(input: CreateDelegationJobInput): Delegation
|
|
|
85
77
|
completedAt: null,
|
|
86
78
|
}
|
|
87
79
|
upsertDelegationJob(job.id, job)
|
|
88
|
-
if (!job.missionId && inferredParentMissionId) {
|
|
89
|
-
const mission = ensureDelegationMission({
|
|
90
|
-
task: job.task,
|
|
91
|
-
backend: job.backend,
|
|
92
|
-
parentSessionId: job.parentSessionId || null,
|
|
93
|
-
childSessionId: job.childSessionId || null,
|
|
94
|
-
agentId: job.agentId || null,
|
|
95
|
-
parentMissionId: inferredParentMissionId,
|
|
96
|
-
jobId: job.id,
|
|
97
|
-
})
|
|
98
|
-
if (mission) {
|
|
99
|
-
job.missionId = mission.id
|
|
100
|
-
upsertDelegationJob(job.id, job)
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
syncDelegationMissionFromJob(job.id)
|
|
104
80
|
notifyDelegationJobsChanged()
|
|
105
81
|
|
|
106
82
|
const sid = job.childSessionId || job.parentSessionId || ''
|
|
@@ -151,7 +127,6 @@ export function updateDelegationJob(
|
|
|
151
127
|
}
|
|
152
128
|
})
|
|
153
129
|
if (!result) return null
|
|
154
|
-
syncDelegationMissionFromJob(id)
|
|
155
130
|
notifyDelegationJobsChanged()
|
|
156
131
|
return getDelegationJob(id) || result
|
|
157
132
|
}
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import { loadAgents } from '@/lib/server/agents/agent-repository'
|
|
11
11
|
import { assessAutonomyRun } from '@/lib/server/autonomy/supervisor-reflection'
|
|
12
12
|
import { enqueueSystemEvent } from '@/lib/server/runtime/system-events'
|
|
13
|
-
import { buildMissionHeartbeatPrompt as buildMissionHeartbeatPromptFromMission, getMissionForSession } from '@/lib/server/missions/mission-service'
|
|
14
13
|
import { loadSettings } from '@/lib/server/settings/settings-repository'
|
|
15
14
|
import { getSession, loadSessions } from '@/lib/server/sessions/session-repository'
|
|
16
15
|
import { deleteSessionWorkingState, loadSessionWorkingState, syncWorkingStateFromMainLoopState } from '@/lib/server/working-state/service'
|
|
@@ -37,7 +36,6 @@ export interface MainLoopState {
|
|
|
37
36
|
currentPlanStep: string | null
|
|
38
37
|
reviewNote: string | null
|
|
39
38
|
reviewConfidence: number | null
|
|
40
|
-
missionTaskId: string | null
|
|
41
39
|
momentumScore: number
|
|
42
40
|
paused: boolean
|
|
43
41
|
status: 'idle' | 'progress' | 'blocked' | 'ok'
|
|
@@ -55,8 +53,6 @@ export interface MainLoopState {
|
|
|
55
53
|
note: string
|
|
56
54
|
status?: 'idle' | 'progress' | 'blocked' | 'ok' | 'reflection'
|
|
57
55
|
}>
|
|
58
|
-
missionTokens: number
|
|
59
|
-
missionCostUsd: number
|
|
60
56
|
followupChainCount: number
|
|
61
57
|
lifetimeIterations: number
|
|
62
58
|
metaMissCount: number
|
|
@@ -137,15 +133,12 @@ function defaultState(): MainLoopState {
|
|
|
137
133
|
currentPlanStep: null,
|
|
138
134
|
reviewNote: null,
|
|
139
135
|
reviewConfidence: null,
|
|
140
|
-
missionTaskId: null,
|
|
141
136
|
momentumScore: 0,
|
|
142
137
|
paused: false,
|
|
143
138
|
status: 'idle',
|
|
144
139
|
autonomyMode: 'assist',
|
|
145
140
|
pendingEvents: [],
|
|
146
141
|
timeline: [],
|
|
147
|
-
missionTokens: 0,
|
|
148
|
-
missionCostUsd: 0,
|
|
149
142
|
followupChainCount: 0,
|
|
150
143
|
lifetimeIterations: 0,
|
|
151
144
|
metaMissCount: 0,
|
|
@@ -304,8 +297,6 @@ function clampState(state: MainLoopState): MainLoopState {
|
|
|
304
297
|
state.followupChainCount = Math.max(0, Math.min(10, Math.trunc(state.followupChainCount || 0)))
|
|
305
298
|
state.lifetimeIterations = Math.max(0, Math.trunc(state.lifetimeIterations || 0))
|
|
306
299
|
state.metaMissCount = Math.max(0, Math.min(100, Math.trunc(state.metaMissCount || 0)))
|
|
307
|
-
state.missionTokens = Math.max(0, Math.trunc(state.missionTokens || 0))
|
|
308
|
-
state.missionCostUsd = Math.max(0, Number.isFinite(state.missionCostUsd) ? Number(state.missionCostUsd) : 0)
|
|
309
300
|
state.skillBlocker = normalizeSkillBlocker(state.skillBlocker)
|
|
310
301
|
state.updatedAt = typeof state.updatedAt === 'number' && Number.isFinite(state.updatedAt) ? Math.trunc(state.updatedAt) : now()
|
|
311
302
|
return state
|
|
@@ -325,15 +316,12 @@ function normalizeState(input?: Partial<MainLoopState> | null): MainLoopState {
|
|
|
325
316
|
if (typeof input.reviewConfidence === 'number' || typeof input.reviewConfidence === 'string' || input.reviewConfidence === null) {
|
|
326
317
|
next.reviewConfidence = normalizeConfidence(input.reviewConfidence)
|
|
327
318
|
}
|
|
328
|
-
if (typeof input.missionTaskId === 'string' || input.missionTaskId === null) next.missionTaskId = input.missionTaskId
|
|
329
319
|
if (typeof input.momentumScore === 'number') next.momentumScore = input.momentumScore
|
|
330
320
|
if (typeof input.paused === 'boolean') next.paused = input.paused
|
|
331
321
|
if (input.status) next.status = normalizeStatus(input.status, next.status)
|
|
332
322
|
if (input.autonomyMode) next.autonomyMode = normalizeAutonomyMode(input.autonomyMode, next.autonomyMode)
|
|
333
323
|
if (Array.isArray(input.pendingEvents)) next.pendingEvents = [...input.pendingEvents]
|
|
334
324
|
if (Array.isArray(input.timeline)) next.timeline = [...input.timeline]
|
|
335
|
-
if (typeof input.missionTokens === 'number') next.missionTokens = input.missionTokens
|
|
336
|
-
if (typeof input.missionCostUsd === 'number') next.missionCostUsd = input.missionCostUsd
|
|
337
325
|
if (typeof input.followupChainCount === 'number') next.followupChainCount = input.followupChainCount
|
|
338
326
|
if (typeof input.lifetimeIterations === 'number') next.lifetimeIterations = input.lifetimeIterations
|
|
339
327
|
if (typeof input.metaMissCount === 'number') next.metaMissCount = input.metaMissCount
|
|
@@ -435,10 +423,8 @@ function persistState(sessionId: string, state: MainLoopState): void {
|
|
|
435
423
|
upsertPersistedMainLoopState(sessionId, normalized as unknown as Record<string, unknown>)
|
|
436
424
|
const session = getSession(sessionId)
|
|
437
425
|
if (!session) return
|
|
438
|
-
const mission = getMissionForSession(session)
|
|
439
426
|
void syncWorkingStateFromMainLoopState({
|
|
440
427
|
sessionId,
|
|
441
|
-
mission,
|
|
442
428
|
goal: normalized.goal,
|
|
443
429
|
summary: normalized.summary,
|
|
444
430
|
status: normalized.status === 'ok'
|
|
@@ -797,11 +783,6 @@ export function buildMainLoopHeartbeatPrompt(session: unknown, fallbackPrompt: s
|
|
|
797
783
|
const candidate = asSession(session)
|
|
798
784
|
if (!candidate?.id) return fallbackPrompt
|
|
799
785
|
const persistedSession = getSession(String(candidate.id)) as Session | undefined
|
|
800
|
-
const missionPrompt = buildMissionHeartbeatPromptFromMission(
|
|
801
|
-
persistedSession || candidate as Session,
|
|
802
|
-
fallbackPrompt,
|
|
803
|
-
)
|
|
804
|
-
if (missionPrompt) return missionPrompt
|
|
805
786
|
const state = getOrCreateState(String(candidate.id))
|
|
806
787
|
if (!state) return fallbackPrompt
|
|
807
788
|
const latestExternalGoal = extractLatestGoal(Array.isArray(candidate.messages) ? candidate.messages as Message[] : [])
|
|
@@ -812,7 +793,6 @@ export function buildMainLoopHeartbeatPrompt(session: unknown, fallbackPrompt: s
|
|
|
812
793
|
const heartbeatSession = (persistedSession || candidate as Session)
|
|
813
794
|
const executionBrief = buildExecutionBrief({
|
|
814
795
|
session: heartbeatSession,
|
|
815
|
-
mission: getMissionForSession(heartbeatSession),
|
|
816
796
|
})
|
|
817
797
|
const executionBriefBlock = buildExecutionBriefContextBlock(executionBrief)
|
|
818
798
|
const boundedFallbackPrompt = cleanMultiline(fallbackPrompt, 500)
|
|
@@ -969,8 +949,6 @@ export function handleMainLoopRunResult(input: HandleMainLoopRunResultInput): Ma
|
|
|
969
949
|
const messageGoal = shouldCaptureMessageGoal ? parseGoalContractFromText(input.message || '') : null
|
|
970
950
|
const nowTs = now()
|
|
971
951
|
state.lifetimeIterations++
|
|
972
|
-
const mission = session ? getMissionForSession(session) : null
|
|
973
|
-
|
|
974
952
|
if (messageGoal) state.goalContract = mergeGoalContracts(state.goalContract, messageGoal)
|
|
975
953
|
if (!state.goal && shouldCaptureMessageGoal) state.goal = cleanMultiline(input.message, 900)
|
|
976
954
|
if (heartbeat?.goal) state.goal = heartbeat.goal
|
|
@@ -1011,8 +989,6 @@ export function handleMainLoopRunResult(input: HandleMainLoopRunResultInput): Ma
|
|
|
1011
989
|
|
|
1012
990
|
state.lastTickAt = nowTs
|
|
1013
991
|
state.updatedAt = nowTs
|
|
1014
|
-
state.missionTokens += Math.max(0, Math.trunc((input.inputTokens || 0) + (input.outputTokens || 0)))
|
|
1015
|
-
state.missionCostUsd += Math.max(0, Number(input.estimatedCost || 0))
|
|
1016
992
|
const cleanedResult = persistedText.trim()
|
|
1017
993
|
const waitingForExternal = extractWaitSignal(resultText)
|
|
1018
994
|
const gotTerminalAck = /^HEARTBEAT_OK$/i.test(cleanedResult) || /^NO_MESSAGE$/i.test(cleanedResult)
|
|
@@ -1073,32 +1049,8 @@ export function handleMainLoopRunResult(input: HandleMainLoopRunResultInput): Ma
|
|
|
1073
1049
|
const needsReplan = review?.needs_replan === true || ((review?.confidence ?? 1) < 0.45)
|
|
1074
1050
|
const limit = followupLimit(input.sessionId)
|
|
1075
1051
|
|
|
1076
|
-
if (mission) {
|
|
1077
|
-
state.goal = cleanMultiline(mission.objective, 900)
|
|
1078
|
-
state.missionTaskId = mission.rootTaskId || null
|
|
1079
|
-
state.summary = cleanMultiline(mission.verifierSummary || mission.plannerSummary || state.summary, 500)
|
|
1080
|
-
state.nextAction = cleanText(mission.currentStep, 280) || null
|
|
1081
|
-
state.currentPlanStep = cleanText(mission.currentStep, 280) || null
|
|
1082
|
-
state.planSteps = mission.currentStep ? [mission.currentStep] : []
|
|
1083
|
-
state.status = mission.status === 'completed'
|
|
1084
|
-
? 'ok'
|
|
1085
|
-
: mission.status === 'waiting' || mission.status === 'failed' || mission.status === 'cancelled'
|
|
1086
|
-
? 'blocked'
|
|
1087
|
-
: 'progress'
|
|
1088
|
-
state.paused = mission.status === 'waiting' || mission.status === 'failed' || mission.status === 'cancelled'
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
1052
|
let followup: MainLoopFollowupRequest | null = null
|
|
1092
|
-
if (
|
|
1093
|
-
state.followupChainCount = 0
|
|
1094
|
-
if (mission.status === 'completed') {
|
|
1095
|
-
state.status = 'ok'
|
|
1096
|
-
state.paused = false
|
|
1097
|
-
}
|
|
1098
|
-
if (mission.status === 'waiting' || mission.status === 'failed' || mission.status === 'cancelled') {
|
|
1099
|
-
state.paused = true
|
|
1100
|
-
}
|
|
1101
|
-
} else if (isDirectUserChat) {
|
|
1053
|
+
if (isDirectUserChat) {
|
|
1102
1054
|
state.followupChainCount = 0
|
|
1103
1055
|
state.lifetimeIterations = 0
|
|
1104
1056
|
if (successfulChatDelivery) {
|
|
@@ -237,7 +237,6 @@ async function spawnSubagentImpl(
|
|
|
237
237
|
const job = createDelegationJob({
|
|
238
238
|
kind: 'subagent',
|
|
239
239
|
parentSessionId: context.sessionId || null,
|
|
240
|
-
parentMissionId: typeof parent?.missionId === 'string' ? parent.missionId : null,
|
|
241
240
|
agentId: input.agentId,
|
|
242
241
|
task: input.message,
|
|
243
242
|
cwd: input.cwd || context.cwd,
|