@swarmclawai/swarmclaw 1.2.6 → 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 +54 -23
- package/next.config.ts +1 -0
- package/package.json +4 -3
- package/scripts/easy-setup.mjs +1 -1
- package/scripts/postinstall.mjs +1 -1
- package/skills/swarmclaw.md +115 -0
- package/skills/tools/browser.md +131 -0
- package/skills/tools/execute.md +98 -0
- package/skills/tools/files.md +98 -0
- package/skills/tools/memory.md +104 -0
- package/skills/tools/platform.md +144 -0
- package/skills/tools/skills.md +83 -0
- 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/chats/[id]/messages/route.ts +23 -19
- package/src/app/api/chats/messages-route.test.ts +105 -51
- package/src/app/api/connectors/route.ts +2 -2
- package/src/app/api/mcp-servers/[id]/test/route.ts +3 -2
- package/src/app/api/openclaw/deploy/route.ts +2 -0
- 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/setup/doctor/route.ts +4 -4
- 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-chat-list.tsx +23 -1
- package/src/components/agents/agent-sheet.tsx +2 -40
- package/src/components/agents/inspector-panel.tsx +165 -131
- package/src/components/chat/chat-area.tsx +38 -9
- package/src/components/chat/chat-card.tsx +0 -31
- package/src/components/chat/message-bubble.tsx +1 -108
- package/src/components/chat/message-list.tsx +33 -19
- package/src/components/connectors/connector-sheet.tsx +25 -1
- package/src/components/gateways/gateway-sheet.tsx +5 -2
- 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/agent-execute-defaults.test.ts +24 -0
- package/src/lib/agent-execute-defaults.ts +62 -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/chat/queued-message-queue.test.ts +134 -1
- package/src/lib/chat/queued-message-queue.ts +77 -2
- package/src/lib/server/agents/agent-service.ts +5 -0
- 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 +1 -2
- package/src/lib/server/capability-router.test.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-advanced.test.ts +1 -1
- package/src/lib/server/chat-execution/chat-execution-tool-events.test.ts +15 -14
- package/src/lib/server/chat-execution/chat-execution-types.ts +0 -2
- package/src/lib/server/chat-execution/chat-execution-utils.ts +2 -4
- 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 +81 -64
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +4 -0
- package/src/lib/server/chat-execution/continuation-evaluator.ts +8 -0
- package/src/lib/server/chat-execution/iteration-event-handler.ts +0 -24
- package/src/lib/server/chat-execution/memory-mutation-tools.ts +1 -1
- package/src/lib/server/chat-execution/message-classifier.test.ts +0 -45
- package/src/lib/server/chat-execution/message-classifier.ts +11 -16
- package/src/lib/server/chat-execution/prompt-builder.test.ts +27 -0
- package/src/lib/server/chat-execution/prompt-builder.ts +14 -31
- package/src/lib/server/chat-execution/prompt-mode.test.ts +24 -0
- package/src/lib/server/chat-execution/prompt-mode.ts +5 -1
- 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 +13 -126
- package/src/lib/server/chat-execution/stream-agent-chat.ts +46 -21
- 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/chatroom-routing.test.ts +4 -0
- 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/discord.ts +2 -2
- package/src/lib/server/connectors/matrix.ts +3 -2
- package/src/lib/server/connectors/signal.ts +5 -4
- package/src/lib/server/connectors/slack.ts +10 -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/connectors/teams.ts +3 -2
- package/src/lib/server/connectors/telegram.ts +4 -4
- package/src/lib/server/connectors/whatsapp.ts +2 -2
- package/src/lib/server/daemon/controller.ts +7 -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/gateways/gateway-profile-service.ts +19 -1
- package/src/lib/server/messages/message-repository.test.ts +70 -0
- package/src/lib/server/messages/message-repository.ts +11 -6
- package/src/lib/server/openclaw/deploy.ts +32 -2
- package/src/lib/server/persistence/storage-context.ts +0 -5
- package/src/lib/server/plugins-advanced.test.ts +1 -2
- 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 +1 -10
- 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/process-manager.ts +13 -9
- 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 +15 -1
- package/src/lib/server/runtime/session-run-manager/recovery.ts +0 -1
- package/src/lib/server/runtime/session-run-manager.test.ts +58 -28
- package/src/lib/server/sandbox/session-runtime.test.ts +18 -1
- package/src/lib/server/sandbox/session-runtime.ts +40 -28
- package/src/lib/server/session-tools/autonomy-tools.test.ts +7 -9
- package/src/lib/server/session-tools/context.ts +1 -1
- package/src/lib/server/session-tools/credential-env.ts +109 -0
- package/src/lib/server/session-tools/crud.ts +3 -17
- package/src/lib/server/session-tools/delegate.ts +0 -4
- package/src/lib/server/session-tools/edit_file.ts +3 -2
- package/src/lib/server/session-tools/execute.test.ts +58 -0
- package/src/lib/server/session-tools/execute.ts +334 -0
- package/src/lib/server/session-tools/files-tool.ts +635 -0
- package/src/lib/server/session-tools/index.ts +14 -8
- package/src/lib/server/session-tools/memory-tool.ts +242 -0
- package/src/lib/server/session-tools/memory.ts +1 -1
- package/src/lib/server/session-tools/openclaw-nodes.ts +3 -2
- package/src/lib/server/session-tools/openclaw-workspace.ts +3 -2
- package/src/lib/server/session-tools/platform-tool.ts +617 -0
- package/src/lib/server/session-tools/session-info.ts +3 -2
- package/src/lib/server/session-tools/session-tools-wiring.test.ts +3 -4
- package/src/lib/server/session-tools/shell.ts +7 -122
- package/src/lib/server/session-tools/skills-tool.ts +396 -0
- package/src/lib/server/session-tools/team-context.ts +0 -3
- package/src/lib/server/session-tools/web.ts +2 -2
- package/src/lib/server/storage-normalization.ts +10 -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 +2 -2
- package/src/lib/server/tool-capability-policy-advanced.test.ts +13 -6
- package/src/lib/server/tool-capability-policy.test.ts +2 -1
- package/src/lib/server/tool-capability-policy.ts +60 -35
- package/src/lib/server/tool-planning.ts +11 -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/setup-defaults.ts +5 -0
- 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 +1 -1
- package/src/lib/validation/schemas.test.ts +16 -0
- package/src/lib/validation/schemas.ts +49 -2
- package/src/stores/slices/data-slice.ts +5 -1
- package/src/stores/slices/ui-slice.ts +0 -4
- package/src/stores/use-chat-store.test.ts +231 -0
- package/src/stores/use-chat-store.ts +62 -13
- package/src/types/agent.ts +264 -0
- package/src/types/app-settings.ts +173 -0
- package/src/types/approval.ts +25 -0
- package/src/types/connector.ts +188 -0
- package/src/types/extension.ts +386 -0
- package/src/types/index.ts +16 -3555
- package/src/types/message.ts +56 -0
- package/src/types/misc.ts +737 -0
- package/src/types/protocol.ts +420 -0
- package/src/types/provider.ts +52 -0
- package/src/types/run.ts +180 -0
- package/src/types/schedule.ts +59 -0
- package/src/types/session.ts +215 -0
- package/src/types/skill.ts +157 -0
- package/src/types/swarmdock.ts +29 -0
- package/src/types/task.ts +144 -0
- package/src/types/working-state.ts +204 -0
- package/src/views/settings/section-heartbeat.tsx +2 -2
- 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/sandbox.ts +0 -281
- 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/views/settings/section-wallets.tsx +0 -35
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { genId } from '@/lib/id'
|
|
2
|
+
import { loadWallets, loadWallet, saveWallet, deleteWallet } from './wallet-repository'
|
|
3
|
+
import { generateEthereumWallet, normalizeEthereumAddress } from './wallet-crypto'
|
|
4
|
+
import { logActivity } from '@/lib/server/activity/activity-log'
|
|
5
|
+
import { loadAgent } from '@/lib/server/agents/agent-repository'
|
|
6
|
+
import type { AgentWallet, SafeWallet } from '@/types/swarmdock'
|
|
7
|
+
|
|
8
|
+
export class WalletServiceError extends Error {
|
|
9
|
+
status: number
|
|
10
|
+
|
|
11
|
+
constructor(status: number, message: string) {
|
|
12
|
+
super(message)
|
|
13
|
+
this.name = 'WalletServiceError'
|
|
14
|
+
this.status = status
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function stripPrivateKey(wallet: AgentWallet): SafeWallet {
|
|
19
|
+
const { encryptedPrivateKey: _, ...safe } = wallet
|
|
20
|
+
return safe
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function requireAgent(agentId: string): string {
|
|
24
|
+
const normalizedAgentId = agentId.trim()
|
|
25
|
+
if (!normalizedAgentId) {
|
|
26
|
+
throw new WalletServiceError(400, 'agentId is required')
|
|
27
|
+
}
|
|
28
|
+
if (!loadAgent(normalizedAgentId)) {
|
|
29
|
+
throw new WalletServiceError(404, `Agent not found: ${normalizedAgentId}`)
|
|
30
|
+
}
|
|
31
|
+
return normalizedAgentId
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function requireWalletAddress(walletAddress: string): Promise<string> {
|
|
35
|
+
const normalizedAddress = walletAddress.trim()
|
|
36
|
+
if (!normalizedAddress) {
|
|
37
|
+
throw new WalletServiceError(400, 'walletAddress is required')
|
|
38
|
+
}
|
|
39
|
+
const checksumAddress = await normalizeEthereumAddress(normalizedAddress)
|
|
40
|
+
if (!checksumAddress) {
|
|
41
|
+
throw new WalletServiceError(400, 'walletAddress must be a valid Base/Ethereum address')
|
|
42
|
+
}
|
|
43
|
+
return checksumAddress
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function listWalletsSafe(): Record<string, SafeWallet> {
|
|
47
|
+
const wallets = loadWallets()
|
|
48
|
+
const safe: Record<string, SafeWallet> = {}
|
|
49
|
+
for (const [id, w] of Object.entries(wallets)) {
|
|
50
|
+
safe[id] = stripPrivateKey(w)
|
|
51
|
+
}
|
|
52
|
+
return safe
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getWalletSafe(id: string): SafeWallet | null {
|
|
56
|
+
const wallet = loadWallet(id)
|
|
57
|
+
return wallet ? stripPrivateKey(wallet) : null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Generate a new Base L2 Ethereum wallet with encrypted private key storage. */
|
|
61
|
+
export async function generateWallet(params: { agentId: string; label?: string }): Promise<SafeWallet> {
|
|
62
|
+
const agentId = requireAgent(params.agentId)
|
|
63
|
+
const { address, encryptedPrivateKey } = await generateEthereumWallet()
|
|
64
|
+
const id = genId()
|
|
65
|
+
const wallet: AgentWallet = {
|
|
66
|
+
id,
|
|
67
|
+
agentId,
|
|
68
|
+
walletAddress: address,
|
|
69
|
+
chain: 'base',
|
|
70
|
+
label: params.label || 'Base L2 Wallet',
|
|
71
|
+
encryptedPrivateKey,
|
|
72
|
+
requireApproval: true,
|
|
73
|
+
createdAt: Date.now(),
|
|
74
|
+
}
|
|
75
|
+
saveWallet(id, wallet)
|
|
76
|
+
logActivity({ entityType: 'wallet', entityId: id, action: 'created', actor: 'user', summary: `Wallet generated: ${address}` })
|
|
77
|
+
return stripPrivateKey(wallet)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Create a wallet from an existing address (no key generation). */
|
|
81
|
+
export async function createWallet(params: { agentId: string; walletAddress: string; label?: string }): Promise<SafeWallet> {
|
|
82
|
+
const agentId = requireAgent(params.agentId)
|
|
83
|
+
const walletAddress = await requireWalletAddress(params.walletAddress)
|
|
84
|
+
const id = genId()
|
|
85
|
+
const wallet: AgentWallet = {
|
|
86
|
+
id,
|
|
87
|
+
agentId,
|
|
88
|
+
walletAddress,
|
|
89
|
+
chain: 'base',
|
|
90
|
+
label: params.label,
|
|
91
|
+
createdAt: Date.now(),
|
|
92
|
+
}
|
|
93
|
+
saveWallet(id, wallet)
|
|
94
|
+
logActivity({ entityType: 'wallet', entityId: id, action: 'created', actor: 'user', summary: `Wallet created: ${walletAddress}` })
|
|
95
|
+
return stripPrivateKey(wallet)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Update wallet settings (label, limits, approval). */
|
|
99
|
+
export function updateWallet(
|
|
100
|
+
id: string,
|
|
101
|
+
patch: Partial<Pick<AgentWallet, 'label' | 'spendingLimitUsdc' | 'dailyLimitUsdc' | 'requireApproval'>>,
|
|
102
|
+
): SafeWallet | null {
|
|
103
|
+
const wallet = loadWallet(id)
|
|
104
|
+
if (!wallet) return null
|
|
105
|
+
if (patch.label !== undefined) wallet.label = patch.label
|
|
106
|
+
if (patch.spendingLimitUsdc !== undefined) wallet.spendingLimitUsdc = patch.spendingLimitUsdc
|
|
107
|
+
if (patch.dailyLimitUsdc !== undefined) wallet.dailyLimitUsdc = patch.dailyLimitUsdc
|
|
108
|
+
if (patch.requireApproval !== undefined) wallet.requireApproval = patch.requireApproval
|
|
109
|
+
saveWallet(id, wallet)
|
|
110
|
+
return stripPrivateKey(wallet)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function removeWallet(id: string): boolean {
|
|
114
|
+
const wallet = loadWallet(id)
|
|
115
|
+
if (!wallet) return false
|
|
116
|
+
deleteWallet(id)
|
|
117
|
+
logActivity({ entityType: 'wallet', entityId: id, action: 'deleted', actor: 'user', summary: `Wallet deleted: ${wallet.walletAddress}` })
|
|
118
|
+
return true
|
|
119
|
+
}
|
|
@@ -22,7 +22,6 @@ import type {
|
|
|
22
22
|
import {
|
|
23
23
|
EXTRACTION_TIMEOUT_MS,
|
|
24
24
|
WorkingStatePatchSchema,
|
|
25
|
-
missionStatusToWorkingStateStatus,
|
|
26
25
|
normalizeEvidenceIds,
|
|
27
26
|
now,
|
|
28
27
|
} from '@/lib/server/working-state/normalization'
|
|
@@ -268,9 +267,9 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
|
|
|
268
267
|
'You maintain a structured working-state object for an autonomous agent.',
|
|
269
268
|
'Return JSON only.',
|
|
270
269
|
'',
|
|
271
|
-
'Update the state using only evidence from the latest turn
|
|
270
|
+
'Update the state using only evidence from the latest turn and tool results.',
|
|
272
271
|
'Rules:',
|
|
273
|
-
'- Facts must be confirmed by explicit user text
|
|
272
|
+
'- Facts must be confirmed by explicit user text or tool evidence. Do not turn guesses into facts.',
|
|
274
273
|
'- Put uncertain leads into hypotheses, not facts.',
|
|
275
274
|
'- Use blockers for approvals, credentials, human input, external waits, and explicit execution failures.',
|
|
276
275
|
'- nextAction must be one concrete immediate action, not a broad plan.',
|
|
@@ -288,7 +287,7 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
|
|
|
288
287
|
status: 'idle|progress|blocked|waiting|completed',
|
|
289
288
|
nextAction: 'optional',
|
|
290
289
|
planSteps: [{ id: 'optional', text: 'step', status: 'active|resolved|superseded' }],
|
|
291
|
-
factsUpsert: [{ id: 'optional', statement: 'confirmed fact', source: 'user|tool|assistant|
|
|
290
|
+
factsUpsert: [{ id: 'optional', statement: 'confirmed fact', source: 'user|tool|assistant|system', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
292
291
|
artifactsUpsert: [{ id: 'optional', label: 'artifact', kind: 'file|url|approval|message|other', path: 'optional', url: 'optional', sourceTool: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
293
292
|
decisionsAppend: [{ summary: 'decision', rationale: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
294
293
|
blockersUpsert: [{ summary: 'blocker', kind: 'approval|credential|human_input|external_dependency|error|other', nextAction: 'optional', status: 'active|resolved|superseded', evidenceIds: ['optional'] }],
|
|
@@ -298,21 +297,6 @@ export function buildWorkingStatePatchPrompt(input: WorkingStateExtractionInput)
|
|
|
298
297
|
}),
|
|
299
298
|
'',
|
|
300
299
|
`source: ${JSON.stringify(cleanText(input.source, 80) || 'chat')}`,
|
|
301
|
-
`mission: ${JSON.stringify(input.mission ? {
|
|
302
|
-
id: input.mission.id,
|
|
303
|
-
objective: cleanMultiline(input.mission.objective, 600),
|
|
304
|
-
status: input.mission.status,
|
|
305
|
-
phase: input.mission.phase,
|
|
306
|
-
currentStep: cleanText(input.mission.currentStep, 240) || null,
|
|
307
|
-
plannerSummary: cleanText(input.mission.plannerSummary, 280) || null,
|
|
308
|
-
verifierSummary: cleanText(input.mission.verifierSummary, 280) || null,
|
|
309
|
-
blockerSummary: cleanText(input.mission.blockerSummary, 240) || null,
|
|
310
|
-
waitState: input.mission.waitState ? {
|
|
311
|
-
kind: input.mission.waitState.kind,
|
|
312
|
-
reason: cleanText(input.mission.waitState.reason, 240),
|
|
313
|
-
approvalId: cleanText(input.mission.waitState.approvalId, 120) || null,
|
|
314
|
-
} : null,
|
|
315
|
-
} : null)}`,
|
|
316
300
|
`current_state:\n${renderStateForExtraction(input.currentState)}`,
|
|
317
301
|
`user_message: ${JSON.stringify(cleanMultiline(input.message, 1200) || null)}`,
|
|
318
302
|
`assistant_text: ${JSON.stringify(cleanMultiline(input.assistantText, 1200) || null)}`,
|
|
@@ -398,7 +382,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
398
382
|
value: input.runId,
|
|
399
383
|
runId: input.runId,
|
|
400
384
|
sessionId: input.sessionId,
|
|
401
|
-
missionId: input.mission?.id || null,
|
|
402
385
|
createdAt: nowTs,
|
|
403
386
|
})
|
|
404
387
|
}
|
|
@@ -420,7 +403,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
420
403
|
toolCallId: cleanText(event.toolCallId, 120) || null,
|
|
421
404
|
runId: input.runId || null,
|
|
422
405
|
sessionId: input.sessionId,
|
|
423
|
-
missionId: input.mission?.id || null,
|
|
424
406
|
createdAt: nowTs + index,
|
|
425
407
|
})
|
|
426
408
|
|
|
@@ -428,7 +410,7 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
428
410
|
blockersUpsert.push({
|
|
429
411
|
summary: output || `Tool ${toolName} failed.`,
|
|
430
412
|
kind: 'error',
|
|
431
|
-
nextAction:
|
|
413
|
+
nextAction: null,
|
|
432
414
|
status: 'active',
|
|
433
415
|
evidenceIds: [evidenceId],
|
|
434
416
|
})
|
|
@@ -521,7 +503,6 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
521
503
|
value: cleanText(input.error, 240) || null,
|
|
522
504
|
runId: input.runId || null,
|
|
523
505
|
sessionId: input.sessionId,
|
|
524
|
-
missionId: input.mission?.id || null,
|
|
525
506
|
createdAt: nowTs + 100,
|
|
526
507
|
})
|
|
527
508
|
blockersUpsert.push({
|
|
@@ -531,26 +512,11 @@ export function deterministicEvidencePatch(input: WorkingStateDeterministicUpdat
|
|
|
531
512
|
})
|
|
532
513
|
}
|
|
533
514
|
|
|
534
|
-
if (input.mission) {
|
|
535
|
-
evidenceAppend.push({
|
|
536
|
-
id: genId(12),
|
|
537
|
-
type: 'mission',
|
|
538
|
-
summary: `Mission state updated: ${input.mission.status}/${input.mission.phase}.`,
|
|
539
|
-
value: cleanText(input.mission.currentStep || input.mission.objective, 240) || null,
|
|
540
|
-
runId: input.runId || null,
|
|
541
|
-
sessionId: input.sessionId,
|
|
542
|
-
missionId: input.mission.id,
|
|
543
|
-
createdAt: nowTs + 200,
|
|
544
|
-
})
|
|
545
|
-
}
|
|
546
|
-
|
|
547
515
|
return {
|
|
548
516
|
status: input.error
|
|
549
517
|
? 'blocked'
|
|
550
|
-
:
|
|
551
|
-
|
|
552
|
-
: undefined,
|
|
553
|
-
nextAction: cleanText(input.mission?.currentStep, 240) || undefined,
|
|
518
|
+
: undefined,
|
|
519
|
+
nextAction: undefined,
|
|
554
520
|
factsUpsert: factsUpsert.length > 0 ? factsUpsert : undefined,
|
|
555
521
|
artifactsUpsert: artifactsUpsert.length > 0 ? artifactsUpsert : undefined,
|
|
556
522
|
blockersUpsert: blockersUpsert.length > 0 ? blockersUpsert : undefined,
|
|
@@ -608,7 +574,7 @@ export function shouldExtractStructuredPatch(input: SynchronizeWorkingStateForTu
|
|
|
608
574
|
const hasAssistantText = cleanMultiline(input.assistantText, 400).length > 0
|
|
609
575
|
const hasError = cleanText(input.error, 120).length > 0
|
|
610
576
|
if (cleanText(input.source, 80) === 'heartbeat') {
|
|
611
|
-
return hasToolEvents || hasError
|
|
577
|
+
return hasToolEvents || hasError
|
|
612
578
|
}
|
|
613
|
-
return hasToolEvents || hasAssistantText || hasMessage || hasError
|
|
579
|
+
return hasToolEvents || hasAssistantText || hasMessage || hasError
|
|
614
580
|
}
|
|
@@ -4,7 +4,6 @@ import { genId } from '@/lib/id'
|
|
|
4
4
|
import { cleanText, cleanMultiline, normalizeList } from '@/lib/server/text-normalization'
|
|
5
5
|
import type {
|
|
6
6
|
EvidenceRef,
|
|
7
|
-
Mission,
|
|
8
7
|
SessionWorkingState,
|
|
9
8
|
WorkingArtifact,
|
|
10
9
|
WorkingArtifactPatch,
|
|
@@ -56,7 +55,7 @@ export const WorkingPlanStepPatchSchema = z.object({
|
|
|
56
55
|
export const WorkingFactPatchSchema = z.object({
|
|
57
56
|
id: z.string().optional().nullable(),
|
|
58
57
|
statement: z.string().optional().nullable(),
|
|
59
|
-
source: z.enum(['user', 'tool', 'assistant', '
|
|
58
|
+
source: z.enum(['user', 'tool', 'assistant', 'system']).optional().nullable(),
|
|
60
59
|
status: WorkingItemStatusSchema.optional().nullable(),
|
|
61
60
|
evidenceIds: z.array(z.string()).optional().nullable(),
|
|
62
61
|
})
|
|
@@ -150,7 +149,6 @@ import type { MessageToolEvent } from '@/types'
|
|
|
150
149
|
|
|
151
150
|
export interface WorkingStateDeterministicUpdateInput {
|
|
152
151
|
sessionId: string
|
|
153
|
-
mission?: Mission | null
|
|
154
152
|
message?: string | null
|
|
155
153
|
assistantText?: string | null
|
|
156
154
|
error?: string | null
|
|
@@ -233,7 +231,6 @@ export function normalizeEvidenceRef(input: unknown): EvidenceRef | null {
|
|
|
233
231
|
if (!summary) return null
|
|
234
232
|
const type = record.type === 'tool'
|
|
235
233
|
|| record.type === 'message'
|
|
236
|
-
|| record.type === 'mission'
|
|
237
234
|
|| record.type === 'task'
|
|
238
235
|
|| record.type === 'artifact'
|
|
239
236
|
|| record.type === 'error'
|
|
@@ -249,7 +246,6 @@ export function normalizeEvidenceRef(input: unknown): EvidenceRef | null {
|
|
|
249
246
|
toolCallId: cleanText(record.toolCallId, 120) || null,
|
|
250
247
|
runId: cleanText(record.runId, 120) || null,
|
|
251
248
|
sessionId: cleanText(record.sessionId, 120) || null,
|
|
252
|
-
missionId: cleanText(record.missionId, 120) || null,
|
|
253
249
|
taskId: cleanText(record.taskId, 120) || null,
|
|
254
250
|
createdAt: typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
|
|
255
251
|
? Math.trunc(record.createdAt)
|
|
@@ -290,7 +286,6 @@ export function normalizeFact(input: unknown): WorkingFact | null {
|
|
|
290
286
|
source: record.source === 'user'
|
|
291
287
|
|| record.source === 'tool'
|
|
292
288
|
|| record.source === 'assistant'
|
|
293
|
-
|| record.source === 'mission'
|
|
294
289
|
|| record.source === 'system'
|
|
295
290
|
? record.source
|
|
296
291
|
: 'assistant',
|
|
@@ -434,17 +429,16 @@ export function normalizeMatchKey(value: string): string {
|
|
|
434
429
|
// defaultWorkingState & normalizeWorkingState
|
|
435
430
|
// ---------------------------------------------------------------------------
|
|
436
431
|
|
|
437
|
-
export function defaultWorkingState(sessionId: string
|
|
432
|
+
export function defaultWorkingState(sessionId: string): SessionWorkingState {
|
|
438
433
|
const nowTs = now()
|
|
439
434
|
return {
|
|
440
435
|
sessionId,
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
summary: cleanMultiline(mission?.verifierSummary || mission?.plannerSummary, 600) || null,
|
|
436
|
+
objective: null,
|
|
437
|
+
summary: null,
|
|
444
438
|
constraints: [],
|
|
445
|
-
successCriteria:
|
|
446
|
-
status:
|
|
447
|
-
nextAction:
|
|
439
|
+
successCriteria: [],
|
|
440
|
+
status: 'idle',
|
|
441
|
+
nextAction: null,
|
|
448
442
|
planSteps: [],
|
|
449
443
|
confirmedFacts: [],
|
|
450
444
|
artifacts: [],
|
|
@@ -462,19 +456,17 @@ export function defaultWorkingState(sessionId: string, mission?: Mission | null)
|
|
|
462
456
|
export function normalizeWorkingState(
|
|
463
457
|
input: unknown,
|
|
464
458
|
sessionId: string,
|
|
465
|
-
mission?: Mission | null,
|
|
466
459
|
): SessionWorkingState {
|
|
467
460
|
if (!input || typeof input !== 'object' || Array.isArray(input)) {
|
|
468
|
-
return defaultWorkingState(sessionId
|
|
461
|
+
return defaultWorkingState(sessionId)
|
|
469
462
|
}
|
|
470
463
|
const record = input as Record<string, unknown>
|
|
471
|
-
const base = defaultWorkingState(sessionId
|
|
464
|
+
const base = defaultWorkingState(sessionId)
|
|
472
465
|
const createdAt = typeof record.createdAt === 'number' && Number.isFinite(record.createdAt)
|
|
473
466
|
? Math.trunc(record.createdAt)
|
|
474
467
|
: base.createdAt
|
|
475
468
|
const normalized: SessionWorkingState = {
|
|
476
469
|
sessionId: cleanText(record.sessionId, 120) || sessionId,
|
|
477
|
-
missionId: cleanText(record.missionId, 120) || mission?.id || null,
|
|
478
470
|
objective: cleanMultiline(record.objective, 900) || base.objective,
|
|
479
471
|
summary: cleanMultiline(record.summary, 600) || base.summary,
|
|
480
472
|
constraints: normalizeList(record.constraints, 12, 240),
|
|
@@ -497,7 +489,7 @@ export function normalizeWorkingState(
|
|
|
497
489
|
? Math.trunc(record.lastCompactedAt)
|
|
498
490
|
: null,
|
|
499
491
|
}
|
|
500
|
-
return compactWorkingStateObject(
|
|
492
|
+
return compactWorkingStateObject(normalized)
|
|
501
493
|
}
|
|
502
494
|
|
|
503
495
|
// ---------------------------------------------------------------------------
|
|
@@ -522,89 +514,6 @@ export function compactWorkingStateObject(state: SessionWorkingState): SessionWo
|
|
|
522
514
|
}
|
|
523
515
|
|
|
524
516
|
// ---------------------------------------------------------------------------
|
|
525
|
-
// missionStatusToWorkingStateStatus & syncWorkingStateWithMission
|
|
526
|
-
// ---------------------------------------------------------------------------
|
|
527
|
-
|
|
528
|
-
export function missionStatusToWorkingStateStatus(mission: Mission): WorkingStateStatus {
|
|
529
|
-
if (mission.status === 'completed') return 'completed'
|
|
530
|
-
if (mission.status === 'waiting') return 'waiting'
|
|
531
|
-
if (mission.status === 'failed' || mission.status === 'cancelled') return 'blocked'
|
|
532
|
-
return 'progress'
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
export function syncWorkingStateWithMission(
|
|
536
|
-
state: SessionWorkingState,
|
|
537
|
-
mission?: Mission | null,
|
|
538
|
-
): SessionWorkingState {
|
|
539
|
-
if (!mission) return state
|
|
540
|
-
const next = { ...state }
|
|
541
|
-
next.missionId = mission.id
|
|
542
|
-
next.objective = cleanMultiline(mission.objective, 900) || next.objective
|
|
543
|
-
next.successCriteria = normalizeList(mission.successCriteria, 12, 240)
|
|
544
|
-
next.summary = next.summary || cleanMultiline(mission.verifierSummary || mission.plannerSummary, 600) || null
|
|
545
|
-
const missionStatus = missionStatusToWorkingStateStatus(mission)
|
|
546
|
-
if (missionStatus === 'completed' || missionStatus === 'waiting' || missionStatus === 'blocked') {
|
|
547
|
-
next.status = missionStatus
|
|
548
|
-
} else if (next.status === 'idle') {
|
|
549
|
-
next.status = missionStatus
|
|
550
|
-
}
|
|
551
|
-
next.nextAction = next.nextAction || cleanText(mission.currentStep, 240) || null
|
|
552
|
-
|
|
553
|
-
if (mission.currentStep) {
|
|
554
|
-
next.planSteps = upsertItems(next.planSteps, [{
|
|
555
|
-
id: null,
|
|
556
|
-
text: mission.currentStep,
|
|
557
|
-
status: mission.status === 'completed' ? 'resolved' : 'active',
|
|
558
|
-
} satisfies WorkingPlanStepPatch], {
|
|
559
|
-
max: MAX_PLAN_STEPS,
|
|
560
|
-
getPatchId: (patch) => cleanText(patch.id, 120) || null,
|
|
561
|
-
getPatchKey: (patch) => cleanText(patch.text, 240),
|
|
562
|
-
getItemKey: (item) => item.text,
|
|
563
|
-
create: (patch, nowTs) => ({
|
|
564
|
-
id: genId(12),
|
|
565
|
-
text: cleanText(patch.text, 240),
|
|
566
|
-
status: normalizeItemStatus(patch.status),
|
|
567
|
-
createdAt: nowTs,
|
|
568
|
-
updatedAt: nowTs,
|
|
569
|
-
}),
|
|
570
|
-
merge: (current, patch, nowTs) => ({
|
|
571
|
-
...current,
|
|
572
|
-
text: cleanText(patch.text, 240) || current.text,
|
|
573
|
-
status: normalizeItemStatus(patch.status, current.status),
|
|
574
|
-
updatedAt: nowTs,
|
|
575
|
-
}),
|
|
576
|
-
compact: compactPlanSteps,
|
|
577
|
-
})
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
if (mission.waitState?.reason || mission.blockerSummary) {
|
|
581
|
-
const blockerSummary = cleanText(mission.waitState?.reason || mission.blockerSummary, 280)
|
|
582
|
-
if (blockerSummary) {
|
|
583
|
-
next.blockers = upsertItems(next.blockers, [{
|
|
584
|
-
summary: blockerSummary,
|
|
585
|
-
kind: mission.waitState?.kind === 'approval'
|
|
586
|
-
? 'approval'
|
|
587
|
-
: mission.waitState?.kind === 'human_reply'
|
|
588
|
-
? 'human_input'
|
|
589
|
-
: mission.waitState?.kind === 'external_dependency' || mission.waitState?.kind === 'provider'
|
|
590
|
-
? 'external_dependency'
|
|
591
|
-
: mission.status === 'failed'
|
|
592
|
-
? 'error'
|
|
593
|
-
: 'other',
|
|
594
|
-
nextAction: mission.currentStep || null,
|
|
595
|
-
status: mission.status === 'completed' ? 'resolved' : 'active',
|
|
596
|
-
}], blockerUpsertConfig())
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
if (mission.status === 'completed') {
|
|
601
|
-
next.blockers = next.blockers.map((blocker) => blocker.status === 'active'
|
|
602
|
-
? { ...blocker, status: 'resolved', updatedAt: now() }
|
|
603
|
-
: blocker)
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
return next
|
|
607
|
-
}
|
|
608
517
|
|
|
609
518
|
// ---------------------------------------------------------------------------
|
|
610
519
|
// upsertItems & upsertConfig factories
|
|
@@ -647,7 +556,6 @@ export function factUpsertConfig(): UpsertConfig<WorkingFact, WorkingFactPatch>
|
|
|
647
556
|
source: patch.source === 'user'
|
|
648
557
|
|| patch.source === 'tool'
|
|
649
558
|
|| patch.source === 'assistant'
|
|
650
|
-
|| patch.source === 'mission'
|
|
651
559
|
|| patch.source === 'system'
|
|
652
560
|
? patch.source
|
|
653
561
|
: 'assistant',
|
|
@@ -662,7 +570,6 @@ export function factUpsertConfig(): UpsertConfig<WorkingFact, WorkingFactPatch>
|
|
|
662
570
|
source: patch.source === 'user'
|
|
663
571
|
|| patch.source === 'tool'
|
|
664
572
|
|| patch.source === 'assistant'
|
|
665
|
-
|| patch.source === 'mission'
|
|
666
573
|
|| patch.source === 'system'
|
|
667
574
|
? patch.source
|
|
668
575
|
: current.source,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { genId } from '@/lib/id'
|
|
2
2
|
import { cleanText, cleanMultiline, normalizeList } from '@/lib/server/text-normalization'
|
|
3
3
|
import type {
|
|
4
|
-
Mission,
|
|
5
4
|
SessionWorkingState,
|
|
6
5
|
WorkingBlocker,
|
|
7
6
|
WorkingPlanStepPatch,
|
|
@@ -20,7 +19,6 @@ import {
|
|
|
20
19
|
normalizeWorkingState,
|
|
21
20
|
defaultWorkingState,
|
|
22
21
|
compactWorkingStateObject,
|
|
23
|
-
syncWorkingStateWithMission,
|
|
24
22
|
normalizeItemStatus,
|
|
25
23
|
normalizeStateStatus,
|
|
26
24
|
upsertItems,
|
|
@@ -96,8 +94,6 @@ export {
|
|
|
96
94
|
compactPlanSteps,
|
|
97
95
|
defaultWorkingState,
|
|
98
96
|
compactWorkingStateObject,
|
|
99
|
-
missionStatusToWorkingStateStatus,
|
|
100
|
-
syncWorkingStateWithMission,
|
|
101
97
|
// Upsert
|
|
102
98
|
upsertItems,
|
|
103
99
|
factUpsertConfig,
|
|
@@ -142,14 +138,14 @@ export { buildWorkingStatePromptBlockFromState } from '@/lib/server/working-stat
|
|
|
142
138
|
// CRUD / coordination layer
|
|
143
139
|
// ---------------------------------------------------------------------------
|
|
144
140
|
|
|
145
|
-
export function loadSessionWorkingState(sessionId: string
|
|
141
|
+
export function loadSessionWorkingState(sessionId: string): SessionWorkingState | null {
|
|
146
142
|
const stored = loadPersistedWorkingState(sessionId)
|
|
147
|
-
if (!stored
|
|
148
|
-
return normalizeWorkingState(stored, sessionId
|
|
143
|
+
if (!stored) return null
|
|
144
|
+
return normalizeWorkingState(stored, sessionId)
|
|
149
145
|
}
|
|
150
146
|
|
|
151
|
-
export function getOrCreateSessionWorkingState(sessionId: string
|
|
152
|
-
return loadSessionWorkingState(sessionId
|
|
147
|
+
export function getOrCreateSessionWorkingState(sessionId: string): SessionWorkingState {
|
|
148
|
+
return loadSessionWorkingState(sessionId) || defaultWorkingState(sessionId)
|
|
153
149
|
}
|
|
154
150
|
|
|
155
151
|
export function saveSessionWorkingState(state: SessionWorkingState): SessionWorkingState {
|
|
@@ -165,12 +161,10 @@ export function deleteSessionWorkingState(sessionId: string): void {
|
|
|
165
161
|
export function applyWorkingStatePatch(
|
|
166
162
|
sessionId: string,
|
|
167
163
|
patch: WorkingStatePatch,
|
|
168
|
-
options?: { mission?: Mission | null },
|
|
169
164
|
): SessionWorkingState {
|
|
170
|
-
const current = getOrCreateSessionWorkingState(sessionId
|
|
165
|
+
const current = getOrCreateSessionWorkingState(sessionId)
|
|
171
166
|
const next: SessionWorkingState = {
|
|
172
167
|
...current,
|
|
173
|
-
missionId: options?.mission?.id || current.missionId || null,
|
|
174
168
|
objective: patch.objective !== undefined ? (cleanMultiline(patch.objective, 900) || null) : current.objective,
|
|
175
169
|
summary: patch.summary !== undefined ? (cleanMultiline(patch.summary, 600) || null) : current.summary,
|
|
176
170
|
constraints: patch.constraints !== undefined ? normalizeList(patch.constraints, 12, 240) : current.constraints,
|
|
@@ -215,16 +209,15 @@ export function applyWorkingStatePatch(
|
|
|
215
209
|
next.openQuestions = markSuperseded(next.openQuestions, patch.supersedeIds)
|
|
216
210
|
next.hypotheses = markSuperseded(next.hypotheses, patch.supersedeIds)
|
|
217
211
|
|
|
218
|
-
const
|
|
219
|
-
upsertPersistedWorkingState(sessionId,
|
|
220
|
-
return
|
|
212
|
+
const compacted = compactWorkingStateObject(next)
|
|
213
|
+
upsertPersistedWorkingState(sessionId, compacted as unknown as Record<string, unknown>)
|
|
214
|
+
return compacted
|
|
221
215
|
}
|
|
222
216
|
|
|
223
217
|
export function recordWorkingStateEvidence(input: WorkingStateDeterministicUpdateInput): SessionWorkingState {
|
|
224
218
|
return applyWorkingStatePatch(
|
|
225
219
|
input.sessionId,
|
|
226
220
|
deterministicEvidencePatch(input),
|
|
227
|
-
{ mission: input.mission || null },
|
|
228
221
|
)
|
|
229
222
|
}
|
|
230
223
|
|
|
@@ -241,12 +234,11 @@ export async function synchronizeWorkingStateForTurn(
|
|
|
241
234
|
currentState: deterministic,
|
|
242
235
|
}, options)
|
|
243
236
|
if (!patch) return deterministic
|
|
244
|
-
return applyWorkingStatePatch(input.sessionId, patch
|
|
237
|
+
return applyWorkingStatePatch(input.sessionId, patch)
|
|
245
238
|
}
|
|
246
239
|
|
|
247
240
|
export function syncWorkingStateFromMainLoopState(input: {
|
|
248
241
|
sessionId: string
|
|
249
|
-
mission?: Mission | null
|
|
250
242
|
goal?: string | null
|
|
251
243
|
summary?: string | null
|
|
252
244
|
status?: WorkingStateStatus | null
|
|
@@ -281,13 +273,12 @@ export function syncWorkingStateFromMainLoopState(input: {
|
|
|
281
273
|
status: (input.status === 'completed' ? 'resolved' : 'active') as WorkingStateItemStatus,
|
|
282
274
|
})).filter((fact) => fact.statement)
|
|
283
275
|
: undefined,
|
|
284
|
-
}
|
|
276
|
+
})
|
|
285
277
|
}
|
|
286
278
|
|
|
287
279
|
export function buildWorkingStatePromptBlock(
|
|
288
280
|
sessionId: string,
|
|
289
|
-
options?: { mission?: Mission | null },
|
|
290
281
|
): string {
|
|
291
|
-
const state = loadSessionWorkingState(sessionId
|
|
282
|
+
const state = loadSessionWorkingState(sessionId)
|
|
292
283
|
return buildWorkingStatePromptBlockFromState(state)
|
|
293
284
|
}
|
|
@@ -204,6 +204,7 @@ export const SETUP_PROVIDERS: SetupProviderOption[] = [
|
|
|
204
204
|
export const STARTER_AGENT_TOOLS = [
|
|
205
205
|
'memory',
|
|
206
206
|
'files',
|
|
207
|
+
'execute',
|
|
207
208
|
'web_search',
|
|
208
209
|
'web_fetch',
|
|
209
210
|
'browser',
|
|
@@ -363,6 +364,7 @@ export interface StarterKit {
|
|
|
363
364
|
const PERSONAL_AGENT_TOOLS = [
|
|
364
365
|
'memory',
|
|
365
366
|
'files',
|
|
367
|
+
'execute',
|
|
366
368
|
'web_search',
|
|
367
369
|
'web_fetch',
|
|
368
370
|
'browser',
|
|
@@ -374,6 +376,7 @@ const PERSONAL_AGENT_TOOLS = [
|
|
|
374
376
|
const RESEARCH_AGENT_TOOLS = [
|
|
375
377
|
'memory',
|
|
376
378
|
'files',
|
|
379
|
+
'execute',
|
|
377
380
|
'web_search',
|
|
378
381
|
'web_fetch',
|
|
379
382
|
'browser',
|
|
@@ -384,6 +387,7 @@ const RESEARCH_AGENT_TOOLS = [
|
|
|
384
387
|
const BUILDER_AGENT_TOOLS = [
|
|
385
388
|
'memory',
|
|
386
389
|
'files',
|
|
390
|
+
'execute',
|
|
387
391
|
'web_search',
|
|
388
392
|
'web_fetch',
|
|
389
393
|
'browser',
|
|
@@ -397,6 +401,7 @@ const OPERATOR_AGENT_TOOLS = STARTER_AGENT_TOOLS
|
|
|
397
401
|
const OPENCLAW_AGENT_TOOLS = [
|
|
398
402
|
'memory',
|
|
399
403
|
'files',
|
|
404
|
+
'execute',
|
|
400
405
|
'web_search',
|
|
401
406
|
'web_fetch',
|
|
402
407
|
'browser',
|
|
@@ -31,7 +31,7 @@ describe('stripInternalJson', () => {
|
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
it('removes JSON with nested objects when internal keys are present', () => {
|
|
34
|
-
const input = '{ "
|
|
34
|
+
const input = '{ "isDeliverableTask": true, "details": { "amount": 100 } }'
|
|
35
35
|
assert.equal(stripInternalJson(input).trim(), '')
|
|
36
36
|
})
|
|
37
37
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
17
|
const INTERNAL_JSON_KEYS = [
|
|
18
|
-
'isDeliverableTask', 'quality_score', 'isBroadGoal',
|
|
18
|
+
'isDeliverableTask', 'quality_score', 'isBroadGoal',
|
|
19
19
|
'hasHumanSignals', 'explicitToolRequests', 'isResearchSynthesis', 'confidence',
|
|
20
20
|
]
|
|
21
21
|
|
|
@@ -16,13 +16,13 @@ export interface ToolDefinition {
|
|
|
16
16
|
*/
|
|
17
17
|
export const AVAILABLE_TOOLS: ToolDefinition[] = [
|
|
18
18
|
{ id: 'shell', label: 'Shell', description: 'Execute commands in the working directory and manage background processes' },
|
|
19
|
+
{ id: 'execute', label: 'Execute', description: 'Run sandboxed bash scripts with just-bash, with optional host execution when explicitly enabled' },
|
|
19
20
|
{ id: 'files', label: 'Files', description: 'Complete file management: read, write, list, move, copy, delete, and send' },
|
|
20
21
|
{ id: 'edit_file', label: 'Edit File', description: 'Surgical search-and-replace within files' },
|
|
21
22
|
{ id: 'web', label: 'Web', description: 'Search the web, fetch content, and make HTTP API calls' },
|
|
22
23
|
{ id: 'delegate', label: 'Delegate', description: 'Delegate complex tasks to specialized backends (Claude Code, Codex, OpenCode)' },
|
|
23
24
|
{ id: 'browser', label: 'Browser', description: 'Playwright — browse, scrape, interact with web pages' },
|
|
24
25
|
{ id: 'memory', label: 'Memory', description: 'Store and retrieve long-term memories across conversations' },
|
|
25
|
-
{ id: 'wallet', label: 'Wallet', description: 'Manage agent crypto wallet — check balance, send SOL, view transactions', extensionId: 'wallet' },
|
|
26
26
|
{ id: 'monitor', label: 'Monitor', description: 'Durable watch jobs: monitor files, endpoints, tasks, and resume agents on triggers' },
|
|
27
27
|
{ id: 'extension_creator', label: 'Extension Creator', description: 'Design focused extensions for durable capabilities and recurring automations' },
|
|
28
28
|
{ id: 'image_gen', label: 'Image Generation', description: 'Generate images from text prompts using OpenAI, Stability AI, Replicate, fal.ai, and more', extensionId: 'image_gen' },
|
|
@@ -57,4 +57,20 @@ describe('AgentCreateSchema', () => {
|
|
|
57
57
|
assert.equal(parsed.orchestratorMaxCyclesPerDay, 12)
|
|
58
58
|
assert.equal(parsed.sessionResetMode, 'isolated')
|
|
59
59
|
})
|
|
60
|
+
|
|
61
|
+
it('accepts executeConfig for sandboxed execute defaults', () => {
|
|
62
|
+
const parsed = AgentCreateSchema.parse({
|
|
63
|
+
name: 'Builder',
|
|
64
|
+
provider: 'openai',
|
|
65
|
+
executeConfig: {
|
|
66
|
+
backend: 'sandbox',
|
|
67
|
+
network: { enabled: true },
|
|
68
|
+
timeout: 45,
|
|
69
|
+
},
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
assert.equal(parsed.executeConfig?.backend, 'sandbox')
|
|
73
|
+
assert.equal(parsed.executeConfig?.network?.enabled, true)
|
|
74
|
+
assert.equal(parsed.executeConfig?.timeout, 45)
|
|
75
|
+
})
|
|
60
76
|
})
|