@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,617 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* platform-tool — Consolidated platform tool (v2).
|
|
3
|
+
*
|
|
4
|
+
* Single `platform` tool that dispatches dotted actions to existing service
|
|
5
|
+
* functions. Replaces the need to expose separate tools for tasks, chatrooms,
|
|
6
|
+
* connectors, subagents, human-loop, and platform CRUD.
|
|
7
|
+
*
|
|
8
|
+
* Action namespace:
|
|
9
|
+
* tasks.* — Task CRUD and lifecycle
|
|
10
|
+
* communicate.* — Human-loop, connector messaging, delegation, subagent spawn
|
|
11
|
+
* projects.* — Project listing and retrieval
|
|
12
|
+
* chatrooms.* — Chatroom messaging and listing
|
|
13
|
+
* agents.* — Agent listing and retrieval
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { z } from 'zod'
|
|
17
|
+
import { tool, type StructuredToolInterface } from '@langchain/core/tools'
|
|
18
|
+
import type { Extension, ExtensionHooks, BoardTask, BoardTaskStatus, Project, Chatroom } from '@/types'
|
|
19
|
+
import type { ToolBuildContext } from './context'
|
|
20
|
+
import { truncate, MAX_OUTPUT } from './context'
|
|
21
|
+
import { registerNativeCapability } from '../native-capabilities'
|
|
22
|
+
import { normalizeToolInputArgs } from './normalize-tool-args'
|
|
23
|
+
import { errorMessage } from '@/lib/shared-utils'
|
|
24
|
+
import { genId } from '@/lib/id'
|
|
25
|
+
import {
|
|
26
|
+
loadAgents,
|
|
27
|
+
loadTasks,
|
|
28
|
+
loadTask,
|
|
29
|
+
upsertTask,
|
|
30
|
+
loadProjects,
|
|
31
|
+
loadChatrooms,
|
|
32
|
+
loadChatroom,
|
|
33
|
+
saveChatrooms,
|
|
34
|
+
} from '../storage'
|
|
35
|
+
import { notify } from '../ws-hub'
|
|
36
|
+
import { logExecution } from '../execution-log'
|
|
37
|
+
import { logActivity } from '../storage'
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Types
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
interface PlatformActionContext {
|
|
44
|
+
agentId?: string | null
|
|
45
|
+
sessionId?: string | null
|
|
46
|
+
cwd: string
|
|
47
|
+
delegationEnabled?: boolean
|
|
48
|
+
delegationTargetMode?: 'all' | 'selected'
|
|
49
|
+
delegationTargetAgentIds?: string[]
|
|
50
|
+
bctx?: ToolBuildContext
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type ActionHandler = (
|
|
54
|
+
params: Record<string, unknown>,
|
|
55
|
+
ctx: PlatformActionContext,
|
|
56
|
+
) => Promise<string> | string
|
|
57
|
+
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Helpers
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
function requireString(params: Record<string, unknown>, key: string): string {
|
|
63
|
+
const val = typeof params[key] === 'string' ? (params[key] as string).trim() : ''
|
|
64
|
+
if (!val) throw new Error(`${key} is required.`)
|
|
65
|
+
return val
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function optionalString(params: Record<string, unknown>, key: string): string | undefined {
|
|
69
|
+
const val = params[key]
|
|
70
|
+
return typeof val === 'string' && val.trim() ? val.trim() : undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const VALID_TASK_STATUSES: BoardTaskStatus[] = [
|
|
74
|
+
'backlog', 'queued', 'running', 'completed', 'failed', 'cancelled', 'archived', 'deferred',
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
function isValidTaskStatus(value: unknown): value is BoardTaskStatus {
|
|
78
|
+
return typeof value === 'string' && VALID_TASK_STATUSES.includes(value as BoardTaskStatus)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// tasks.* handlers
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
function handleTasksCreate(params: Record<string, unknown>, ctx: PlatformActionContext): string {
|
|
86
|
+
const title = requireString(params, 'title')
|
|
87
|
+
const description = optionalString(params, 'description') || ''
|
|
88
|
+
const assignee = optionalString(params, 'assignee') || optionalString(params, 'agentId') || ctx.agentId || ''
|
|
89
|
+
const status: BoardTaskStatus = isValidTaskStatus(params.status) ? params.status : 'backlog'
|
|
90
|
+
const projectId = optionalString(params, 'projectId')
|
|
91
|
+
|
|
92
|
+
const now = Date.now()
|
|
93
|
+
const task: BoardTask = {
|
|
94
|
+
id: genId(),
|
|
95
|
+
title,
|
|
96
|
+
description,
|
|
97
|
+
status,
|
|
98
|
+
agentId: assignee,
|
|
99
|
+
projectId,
|
|
100
|
+
createdByAgentId: ctx.agentId || null,
|
|
101
|
+
createdInSessionId: ctx.sessionId || null,
|
|
102
|
+
createdAt: now,
|
|
103
|
+
updatedAt: now,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
upsertTask(task.id, task)
|
|
107
|
+
notify('tasks')
|
|
108
|
+
|
|
109
|
+
logActivity({
|
|
110
|
+
entityType: 'task',
|
|
111
|
+
entityId: task.id,
|
|
112
|
+
action: 'created',
|
|
113
|
+
actor: 'agent',
|
|
114
|
+
actorId: ctx.agentId || undefined,
|
|
115
|
+
summary: `Task created: ${title}`,
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
return JSON.stringify({ ok: true, task: { id: task.id, title, status, agentId: assignee, projectId } })
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function handleTasksUpdate(params: Record<string, unknown>, ctx: PlatformActionContext): string {
|
|
122
|
+
const taskId = requireString(params, 'taskId')
|
|
123
|
+
const existing = loadTask(taskId)
|
|
124
|
+
if (!existing) return `Error: task "${taskId}" not found.`
|
|
125
|
+
|
|
126
|
+
const updates: Partial<BoardTask> = { updatedAt: Date.now() }
|
|
127
|
+
if (typeof params.title === 'string' && params.title.trim()) updates.title = params.title.trim()
|
|
128
|
+
if (typeof params.description === 'string') updates.description = params.description.trim()
|
|
129
|
+
if (isValidTaskStatus(params.status)) updates.status = params.status
|
|
130
|
+
if (typeof params.result === 'string') updates.result = params.result.trim()
|
|
131
|
+
if (typeof params.agentId === 'string') updates.agentId = params.agentId.trim()
|
|
132
|
+
if (typeof params.projectId === 'string') updates.projectId = params.projectId.trim()
|
|
133
|
+
|
|
134
|
+
if (updates.status === 'completed' && !existing.completedAt) {
|
|
135
|
+
updates.completedAt = Date.now()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const merged = { ...existing, ...updates }
|
|
139
|
+
upsertTask(taskId, merged)
|
|
140
|
+
notify('tasks')
|
|
141
|
+
|
|
142
|
+
logActivity({
|
|
143
|
+
entityType: 'task',
|
|
144
|
+
entityId: taskId,
|
|
145
|
+
action: 'updated',
|
|
146
|
+
actor: 'agent',
|
|
147
|
+
actorId: ctx.agentId || undefined,
|
|
148
|
+
summary: `Task updated: ${merged.title}`,
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
return JSON.stringify({ ok: true, task: { id: taskId, title: merged.title, status: merged.status } })
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function handleTasksList(params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
155
|
+
const all = loadTasks()
|
|
156
|
+
let tasks = Object.values(all) as BoardTask[]
|
|
157
|
+
|
|
158
|
+
// Optional filters
|
|
159
|
+
const filterStatus = optionalString(params, 'status')
|
|
160
|
+
const filterAgentId = optionalString(params, 'agentId') || optionalString(params, 'assignee')
|
|
161
|
+
const filterProjectId = optionalString(params, 'projectId')
|
|
162
|
+
|
|
163
|
+
if (filterStatus && isValidTaskStatus(filterStatus)) {
|
|
164
|
+
tasks = tasks.filter((t) => t.status === filterStatus)
|
|
165
|
+
}
|
|
166
|
+
if (filterAgentId) {
|
|
167
|
+
tasks = tasks.filter((t) => t.agentId === filterAgentId)
|
|
168
|
+
}
|
|
169
|
+
if (filterProjectId) {
|
|
170
|
+
tasks = tasks.filter((t) => t.projectId === filterProjectId)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Default: exclude archived
|
|
174
|
+
if (!filterStatus) {
|
|
175
|
+
tasks = tasks.filter((t) => t.status !== 'archived')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
tasks.sort((a, b) => b.updatedAt - a.updatedAt)
|
|
179
|
+
|
|
180
|
+
const limit = typeof params.limit === 'number' ? Math.min(params.limit, 100) : 50
|
|
181
|
+
const summary = tasks.slice(0, limit).map((t) => ({
|
|
182
|
+
id: t.id,
|
|
183
|
+
title: t.title,
|
|
184
|
+
status: t.status,
|
|
185
|
+
agentId: t.agentId,
|
|
186
|
+
projectId: t.projectId || null,
|
|
187
|
+
updatedAt: t.updatedAt,
|
|
188
|
+
}))
|
|
189
|
+
return JSON.stringify(summary)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function handleTasksGet(params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
193
|
+
const taskId = requireString(params, 'taskId')
|
|
194
|
+
const task = loadTask(taskId)
|
|
195
|
+
if (!task) return `Error: task "${taskId}" not found.`
|
|
196
|
+
return JSON.stringify(task)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function handleTasksComplete(params: Record<string, unknown>, ctx: PlatformActionContext): string {
|
|
200
|
+
const taskId = requireString(params, 'taskId')
|
|
201
|
+
const existing = loadTask(taskId)
|
|
202
|
+
if (!existing) return `Error: task "${taskId}" not found.`
|
|
203
|
+
|
|
204
|
+
const result = optionalString(params, 'result') || 'Completed'
|
|
205
|
+
const now = Date.now()
|
|
206
|
+
const merged: BoardTask = {
|
|
207
|
+
...existing,
|
|
208
|
+
status: 'completed',
|
|
209
|
+
result,
|
|
210
|
+
completedAt: now,
|
|
211
|
+
updatedAt: now,
|
|
212
|
+
}
|
|
213
|
+
upsertTask(taskId, merged)
|
|
214
|
+
notify('tasks')
|
|
215
|
+
|
|
216
|
+
logActivity({
|
|
217
|
+
entityType: 'task',
|
|
218
|
+
entityId: taskId,
|
|
219
|
+
action: 'completed',
|
|
220
|
+
actor: 'agent',
|
|
221
|
+
actorId: ctx.agentId || undefined,
|
|
222
|
+
summary: `Task completed: ${merged.title}`,
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
return JSON.stringify({ ok: true, task: { id: taskId, title: merged.title, status: 'completed', result } })
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
// communicate.* handlers
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
|
|
232
|
+
async function handleCommunicateAskHuman(
|
|
233
|
+
params: Record<string, unknown>,
|
|
234
|
+
ctx: PlatformActionContext,
|
|
235
|
+
): Promise<string> {
|
|
236
|
+
// Delegate to the existing human-loop executeHumanLoopAction logic
|
|
237
|
+
// by dynamically importing to avoid circular deps
|
|
238
|
+
const { buildHumanLoopTools } = await import('./human-loop')
|
|
239
|
+
const bctx = ctx.bctx
|
|
240
|
+
if (!bctx) return 'Error: build context not available for ask_human.'
|
|
241
|
+
|
|
242
|
+
// Determine the sub-action: map communicate.ask_human params to human-loop actions
|
|
243
|
+
const subAction = optionalString(params, 'subAction') || 'request_input'
|
|
244
|
+
const humanArgs: Record<string, unknown> = {
|
|
245
|
+
...params,
|
|
246
|
+
action: subAction,
|
|
247
|
+
}
|
|
248
|
+
// Remove our routing keys
|
|
249
|
+
delete humanArgs.subAction
|
|
250
|
+
|
|
251
|
+
// Build the human-loop tool and invoke it
|
|
252
|
+
const tools = buildHumanLoopTools(bctx)
|
|
253
|
+
if (tools.length === 0) return 'Error: ask_human extension is not enabled.'
|
|
254
|
+
const result = await tools[0].invoke(humanArgs)
|
|
255
|
+
const resultStr = typeof result === 'string' ? result : JSON.stringify(result)
|
|
256
|
+
|
|
257
|
+
// Tag durable_wait outputs so the terminal boundary resolver can detect them
|
|
258
|
+
if (
|
|
259
|
+
(subAction === 'wait_for_reply' || subAction === 'wait_for_approval')
|
|
260
|
+
&& resultStr.includes('"status":"active"')
|
|
261
|
+
) {
|
|
262
|
+
// The output already has the right shape for resolveSuccessfulTerminalToolBoundary
|
|
263
|
+
// to detect it via the ask_human canonical name check. But since our tool is named
|
|
264
|
+
// "platform", we embed a marker field so the boundary resolver can be extended.
|
|
265
|
+
try {
|
|
266
|
+
const parsed = JSON.parse(resultStr) as Record<string, unknown>
|
|
267
|
+
return JSON.stringify({
|
|
268
|
+
...parsed,
|
|
269
|
+
__terminal_boundary: 'durable_wait',
|
|
270
|
+
})
|
|
271
|
+
} catch {
|
|
272
|
+
return resultStr
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return resultStr
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async function handleCommunicateSendMessage(
|
|
280
|
+
params: Record<string, unknown>,
|
|
281
|
+
ctx: PlatformActionContext,
|
|
282
|
+
): Promise<string> {
|
|
283
|
+
// Delegate to the existing connector action
|
|
284
|
+
const bctx = ctx.bctx
|
|
285
|
+
if (!bctx) return 'Error: build context not available for send_message.'
|
|
286
|
+
|
|
287
|
+
const { buildConnectorTools } = await import('./connector')
|
|
288
|
+
const tools = buildConnectorTools(bctx)
|
|
289
|
+
if (tools.length === 0) return 'Error: connector_message_tool extension is not enabled.'
|
|
290
|
+
|
|
291
|
+
const connectorArgs: Record<string, unknown> = {
|
|
292
|
+
action: 'send',
|
|
293
|
+
...params,
|
|
294
|
+
}
|
|
295
|
+
const result = await tools[0].invoke(connectorArgs)
|
|
296
|
+
return typeof result === 'string' ? result : JSON.stringify(result)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async function handleCommunicateDelegate(
|
|
300
|
+
params: Record<string, unknown>,
|
|
301
|
+
ctx: PlatformActionContext,
|
|
302
|
+
): Promise<string> {
|
|
303
|
+
const bctx = ctx.bctx
|
|
304
|
+
if (!bctx) return 'Error: build context not available for delegate.'
|
|
305
|
+
|
|
306
|
+
const { buildDelegateTools } = await import('./delegate')
|
|
307
|
+
const tools = buildDelegateTools(bctx)
|
|
308
|
+
if (tools.length === 0) return 'Error: delegate extension is not enabled or delegation is disabled.'
|
|
309
|
+
|
|
310
|
+
const delegateArgs: Record<string, unknown> = {
|
|
311
|
+
action: 'start',
|
|
312
|
+
...params,
|
|
313
|
+
}
|
|
314
|
+
const result = await tools[0].invoke(delegateArgs)
|
|
315
|
+
return typeof result === 'string' ? result : JSON.stringify(result)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async function handleCommunicateSpawn(
|
|
319
|
+
params: Record<string, unknown>,
|
|
320
|
+
ctx: PlatformActionContext,
|
|
321
|
+
): Promise<string> {
|
|
322
|
+
const bctx = ctx.bctx
|
|
323
|
+
if (!bctx) return 'Error: build context not available for spawn.'
|
|
324
|
+
|
|
325
|
+
const { buildSubagentTools } = await import('./subagent')
|
|
326
|
+
const tools = buildSubagentTools(bctx)
|
|
327
|
+
if (tools.length === 0) return 'Error: spawn_subagent extension is not enabled or delegation is disabled.'
|
|
328
|
+
|
|
329
|
+
const subagentArgs: Record<string, unknown> = {
|
|
330
|
+
action: 'start',
|
|
331
|
+
...params,
|
|
332
|
+
}
|
|
333
|
+
const result = await tools[0].invoke(subagentArgs)
|
|
334
|
+
return typeof result === 'string' ? result : JSON.stringify(result)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ---------------------------------------------------------------------------
|
|
338
|
+
// projects.* handlers
|
|
339
|
+
// ---------------------------------------------------------------------------
|
|
340
|
+
|
|
341
|
+
function handleProjectsList(_params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
342
|
+
const all = loadProjects()
|
|
343
|
+
const projects = Object.values(all) as Project[]
|
|
344
|
+
const summary = projects.map((p) => ({
|
|
345
|
+
id: p.id,
|
|
346
|
+
name: p.name,
|
|
347
|
+
description: p.description,
|
|
348
|
+
updatedAt: p.updatedAt,
|
|
349
|
+
}))
|
|
350
|
+
return JSON.stringify(summary)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function handleProjectsGet(params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
354
|
+
const projectId = requireString(params, 'projectId')
|
|
355
|
+
const all = loadProjects()
|
|
356
|
+
const project = (all as Record<string, Project>)[projectId]
|
|
357
|
+
if (!project) return `Error: project "${projectId}" not found.`
|
|
358
|
+
return JSON.stringify(project)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// ---------------------------------------------------------------------------
|
|
362
|
+
// chatrooms.* handlers
|
|
363
|
+
// ---------------------------------------------------------------------------
|
|
364
|
+
|
|
365
|
+
function handleChatroomsSend(params: Record<string, unknown>, ctx: PlatformActionContext): string {
|
|
366
|
+
const chatroomId = requireString(params, 'chatroomId')
|
|
367
|
+
const message = requireString(params, 'message')
|
|
368
|
+
const chatrooms = loadChatrooms() as Record<string, Chatroom>
|
|
369
|
+
const chatroom = chatrooms[chatroomId]
|
|
370
|
+
if (!chatroom) return `Error: chatroom "${chatroomId}" not found.`
|
|
371
|
+
|
|
372
|
+
const agents = loadAgents()
|
|
373
|
+
const senderName = ctx.agentId ? (agents[ctx.agentId]?.name || 'Agent') : 'Agent'
|
|
374
|
+
const msgId = genId()
|
|
375
|
+
const targetAgentId = optionalString(params, 'targetAgentId')
|
|
376
|
+
|
|
377
|
+
chatroom.messages.push({
|
|
378
|
+
id: msgId,
|
|
379
|
+
senderId: ctx.agentId || 'agent',
|
|
380
|
+
senderName,
|
|
381
|
+
role: 'assistant' as const,
|
|
382
|
+
text: message,
|
|
383
|
+
mentions: [],
|
|
384
|
+
reactions: [],
|
|
385
|
+
time: Date.now(),
|
|
386
|
+
...(targetAgentId ? { targetAgentId } : {}),
|
|
387
|
+
})
|
|
388
|
+
chatroom.updatedAt = Date.now()
|
|
389
|
+
saveChatrooms(chatrooms)
|
|
390
|
+
notify(`chatroom:${chatroomId}`)
|
|
391
|
+
|
|
392
|
+
logExecution(ctx.sessionId || '', 'chatroom_message', `Message sent in ${chatroom.name}`, {
|
|
393
|
+
agentId: ctx.agentId,
|
|
394
|
+
detail: { chatroomId, senderId: ctx.agentId, messageLen: message.length },
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
return JSON.stringify({ ok: true, messageId: msgId })
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function handleChatroomsList(_params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
401
|
+
const chatrooms = loadChatrooms() as Record<string, Chatroom>
|
|
402
|
+
const list = Object.values(chatrooms).map((cr) => ({
|
|
403
|
+
id: cr.id,
|
|
404
|
+
name: cr.name,
|
|
405
|
+
description: cr.description,
|
|
406
|
+
memberCount: cr.agentIds.length,
|
|
407
|
+
messageCount: cr.messages.length,
|
|
408
|
+
}))
|
|
409
|
+
return JSON.stringify(list)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
function handleChatroomsHistory(params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
413
|
+
const chatroomId = requireString(params, 'chatroomId')
|
|
414
|
+
const chatroom = loadChatroom(chatroomId)
|
|
415
|
+
if (!chatroom) return `Error: chatroom "${chatroomId}" not found.`
|
|
416
|
+
|
|
417
|
+
const limit = typeof params.limit === 'number' ? Math.min(params.limit, 50) : 20
|
|
418
|
+
const messages = chatroom.messages.slice(-limit).map((msg) => ({
|
|
419
|
+
id: msg.id,
|
|
420
|
+
sender: msg.senderName,
|
|
421
|
+
senderId: msg.senderId,
|
|
422
|
+
text: msg.text.slice(0, 300),
|
|
423
|
+
time: msg.time,
|
|
424
|
+
...(msg.targetAgentId ? { targetAgentId: msg.targetAgentId } : {}),
|
|
425
|
+
...(msg.replyToId ? { replyToId: msg.replyToId } : {}),
|
|
426
|
+
}))
|
|
427
|
+
return JSON.stringify(messages)
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// ---------------------------------------------------------------------------
|
|
431
|
+
// agents.* handlers
|
|
432
|
+
// ---------------------------------------------------------------------------
|
|
433
|
+
|
|
434
|
+
function handleAgentsList(_params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
435
|
+
const all = loadAgents()
|
|
436
|
+
const agents = Object.values(all).map((a) => ({
|
|
437
|
+
id: a.id,
|
|
438
|
+
name: a.name,
|
|
439
|
+
description: a.description || '',
|
|
440
|
+
provider: a.provider,
|
|
441
|
+
model: a.model,
|
|
442
|
+
}))
|
|
443
|
+
return JSON.stringify(agents)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function handleAgentsGet(params: Record<string, unknown>, _ctx: PlatformActionContext): string {
|
|
447
|
+
const agentId = requireString(params, 'agentId')
|
|
448
|
+
const all = loadAgents()
|
|
449
|
+
const agent = all[agentId]
|
|
450
|
+
if (!agent) return `Error: agent "${agentId}" not found.`
|
|
451
|
+
// Return a safe subset — omit API keys and sensitive config
|
|
452
|
+
return JSON.stringify({
|
|
453
|
+
id: agent.id,
|
|
454
|
+
name: agent.name,
|
|
455
|
+
description: agent.description || '',
|
|
456
|
+
provider: agent.provider,
|
|
457
|
+
model: agent.model,
|
|
458
|
+
soul: agent.soul || '',
|
|
459
|
+
capabilities: agent.capabilities || [],
|
|
460
|
+
})
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// ---------------------------------------------------------------------------
|
|
464
|
+
// Action dispatch
|
|
465
|
+
// ---------------------------------------------------------------------------
|
|
466
|
+
|
|
467
|
+
const ACTION_MAP: Record<string, ActionHandler> = {
|
|
468
|
+
// Tasks
|
|
469
|
+
'tasks.create': handleTasksCreate,
|
|
470
|
+
'tasks.update': handleTasksUpdate,
|
|
471
|
+
'tasks.list': handleTasksList,
|
|
472
|
+
'tasks.get': handleTasksGet,
|
|
473
|
+
'tasks.complete': handleTasksComplete,
|
|
474
|
+
|
|
475
|
+
// Communication
|
|
476
|
+
'communicate.ask_human': handleCommunicateAskHuman,
|
|
477
|
+
'communicate.send_message': handleCommunicateSendMessage,
|
|
478
|
+
'communicate.delegate': handleCommunicateDelegate,
|
|
479
|
+
'communicate.spawn': handleCommunicateSpawn,
|
|
480
|
+
|
|
481
|
+
// Projects
|
|
482
|
+
'projects.list': handleProjectsList,
|
|
483
|
+
'projects.get': handleProjectsGet,
|
|
484
|
+
|
|
485
|
+
// Chatrooms
|
|
486
|
+
'chatrooms.send': handleChatroomsSend,
|
|
487
|
+
'chatrooms.list': handleChatroomsList,
|
|
488
|
+
'chatrooms.history': handleChatroomsHistory,
|
|
489
|
+
|
|
490
|
+
// Agents
|
|
491
|
+
'agents.list': handleAgentsList,
|
|
492
|
+
'agents.get': handleAgentsGet,
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
const VALID_ACTIONS = Object.keys(ACTION_MAP)
|
|
496
|
+
|
|
497
|
+
async function executePlatformV2Action(
|
|
498
|
+
args: Record<string, unknown>,
|
|
499
|
+
ctx: PlatformActionContext,
|
|
500
|
+
): Promise<string> {
|
|
501
|
+
const normalized = normalizeToolInputArgs(args)
|
|
502
|
+
const action = typeof normalized.action === 'string'
|
|
503
|
+
? normalized.action.trim().toLowerCase()
|
|
504
|
+
: ''
|
|
505
|
+
|
|
506
|
+
if (!action) {
|
|
507
|
+
return `Error: action is required. Valid actions: ${VALID_ACTIONS.join(', ')}.`
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
const handler = ACTION_MAP[action]
|
|
511
|
+
if (!handler) {
|
|
512
|
+
// Try fuzzy matching — help LLMs that drop the dot or use underscores
|
|
513
|
+
const fuzzyAction = action.replace(/_/g, '.')
|
|
514
|
+
const fuzzyHandler = ACTION_MAP[fuzzyAction]
|
|
515
|
+
if (fuzzyHandler) {
|
|
516
|
+
try {
|
|
517
|
+
const result = await fuzzyHandler(normalized, ctx)
|
|
518
|
+
return truncate(result, MAX_OUTPUT)
|
|
519
|
+
} catch (err: unknown) {
|
|
520
|
+
return `Error: ${errorMessage(err)}`
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return `Error: Unknown action "${action}". Valid actions: ${VALID_ACTIONS.join(', ')}.`
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
try {
|
|
528
|
+
const result = await handler(normalized, ctx)
|
|
529
|
+
return truncate(result, MAX_OUTPUT)
|
|
530
|
+
} catch (err: unknown) {
|
|
531
|
+
return `Error: ${errorMessage(err)}`
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// ---------------------------------------------------------------------------
|
|
536
|
+
// Extension registration
|
|
537
|
+
// ---------------------------------------------------------------------------
|
|
538
|
+
|
|
539
|
+
const PlatformV2Extension: Extension = {
|
|
540
|
+
name: 'Platform V2',
|
|
541
|
+
enabledByDefault: false,
|
|
542
|
+
description: 'Consolidated platform tool for tasks, communication, projects, chatrooms, and agent management.',
|
|
543
|
+
hooks: {
|
|
544
|
+
getCapabilityDescription: () =>
|
|
545
|
+
'I can manage tasks, communicate with humans and other agents, browse projects and chatrooms, and list agents — all via the unified `platform` tool with dotted actions like `tasks.create`, `communicate.ask_human`, `chatrooms.send`.',
|
|
546
|
+
getOperatingGuidance: () => [
|
|
547
|
+
'Use `platform` with action "tasks.create" to create tasks, "tasks.update" to update, "tasks.complete" to mark done.',
|
|
548
|
+
'Use "communicate.ask_human" with subAction "request_input" to ask a human, then "wait_for_reply" to pause. Do not repeat pending questions.',
|
|
549
|
+
'Use "communicate.send_message" to send connector messages, "communicate.delegate" to delegate to CLI agents, "communicate.spawn" to spawn subagents.',
|
|
550
|
+
'Use "projects.list" and "projects.get" for project info, "chatrooms.list" and "chatrooms.send" for chatrooms.',
|
|
551
|
+
'Use "agents.list" and "agents.get" to discover available agents.',
|
|
552
|
+
],
|
|
553
|
+
} as ExtensionHooks,
|
|
554
|
+
tools: [
|
|
555
|
+
{
|
|
556
|
+
name: 'platform',
|
|
557
|
+
description:
|
|
558
|
+
'Consolidated platform tool. Use dotted action names: '
|
|
559
|
+
+ 'tasks.create, tasks.update, tasks.list, tasks.get, tasks.complete, '
|
|
560
|
+
+ 'communicate.ask_human (subAction: request_input|wait_for_reply|wait_for_approval|list_mailbox|ack_mailbox|status), '
|
|
561
|
+
+ 'communicate.send_message, communicate.delegate, communicate.spawn, '
|
|
562
|
+
+ 'projects.list, projects.get, '
|
|
563
|
+
+ 'chatrooms.send, chatrooms.list, chatrooms.history, '
|
|
564
|
+
+ 'agents.list, agents.get.',
|
|
565
|
+
parameters: {
|
|
566
|
+
type: 'object',
|
|
567
|
+
properties: {
|
|
568
|
+
action: {
|
|
569
|
+
type: 'string',
|
|
570
|
+
description: 'Dotted action name, e.g. "tasks.create", "communicate.ask_human"',
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
required: ['action'],
|
|
574
|
+
},
|
|
575
|
+
execute: async (args, context) => {
|
|
576
|
+
const sessionAgentId = context.session.agentId || undefined
|
|
577
|
+
return executePlatformV2Action(args as Record<string, unknown>, {
|
|
578
|
+
agentId: sessionAgentId,
|
|
579
|
+
sessionId: context.session.id,
|
|
580
|
+
cwd: context.session.cwd || process.cwd(),
|
|
581
|
+
})
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
],
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
registerNativeCapability('platform_v2', PlatformV2Extension)
|
|
588
|
+
|
|
589
|
+
// ---------------------------------------------------------------------------
|
|
590
|
+
// Tool builder (called from session-tools/index.ts)
|
|
591
|
+
// ---------------------------------------------------------------------------
|
|
592
|
+
|
|
593
|
+
export function buildPlatformV2Tools(bctx: ToolBuildContext): StructuredToolInterface[] {
|
|
594
|
+
if (!bctx.hasExtension('platform_v2')) return []
|
|
595
|
+
|
|
596
|
+
const sessionAgentId = bctx.ctx?.agentId || undefined
|
|
597
|
+
|
|
598
|
+
return [
|
|
599
|
+
tool(
|
|
600
|
+
async (args) =>
|
|
601
|
+
executePlatformV2Action(args, {
|
|
602
|
+
agentId: sessionAgentId,
|
|
603
|
+
sessionId: bctx.ctx?.sessionId,
|
|
604
|
+
cwd: bctx.cwd,
|
|
605
|
+
delegationEnabled: bctx.ctx?.delegationEnabled,
|
|
606
|
+
delegationTargetMode: bctx.ctx?.delegationTargetMode,
|
|
607
|
+
delegationTargetAgentIds: bctx.ctx?.delegationTargetAgentIds,
|
|
608
|
+
bctx,
|
|
609
|
+
}),
|
|
610
|
+
{
|
|
611
|
+
name: 'platform',
|
|
612
|
+
description: PlatformV2Extension.tools![0].description,
|
|
613
|
+
schema: z.object({}).passthrough(),
|
|
614
|
+
},
|
|
615
|
+
),
|
|
616
|
+
]
|
|
617
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { errorMessage } from '@/lib/shared-utils'
|
|
1
2
|
import { z } from 'zod'
|
|
2
3
|
import { tool, type StructuredToolInterface } from '@langchain/core/tools'
|
|
3
4
|
import { genId } from '@/lib/id'
|
|
@@ -38,7 +39,7 @@ async function executeWhoAmI(context: { sessionId?: string; agentId?: string })
|
|
|
38
39
|
toolPolicy,
|
|
39
40
|
rootSessionId,
|
|
40
41
|
}))
|
|
41
|
-
} catch (err:
|
|
42
|
+
} catch (err: unknown) { return `Error: ${errorMessage(err)}` }
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
function normalizeRuntimeExtensionId(extensionId: string): string {
|
|
@@ -226,7 +227,7 @@ async function executeSessionsAction(args: any, context: { sessionId?: string; a
|
|
|
226
227
|
return JSON.stringify({ sessionId: targetId, updated: Object.keys(patch).filter((key) => allowedKeys.has(key)) })
|
|
227
228
|
}
|
|
228
229
|
return `Unknown action "${action}".`
|
|
229
|
-
} catch (err:
|
|
230
|
+
} catch (err: unknown) { return `Error: ${errorMessage(err)}` }
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
/**
|
|
@@ -115,10 +115,9 @@ describe('buildSessionTools signature', () => {
|
|
|
115
115
|
await built.cleanup()
|
|
116
116
|
})
|
|
117
117
|
|
|
118
|
-
it('
|
|
119
|
-
const
|
|
120
|
-
assert.equal(typeof
|
|
121
|
-
assert.equal(typeof sandbox.executeListRuntimes, 'function')
|
|
118
|
+
it('execute tool builder is importable', async () => {
|
|
119
|
+
const execute = await import('./execute')
|
|
120
|
+
assert.equal(typeof execute.buildExecuteTools, 'function')
|
|
122
121
|
})
|
|
123
122
|
})
|
|
124
123
|
|