@swarmclawai/swarmclaw 1.3.6 → 1.4.0
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 +32 -1
- package/package.json +9 -3
- package/src/.env.local +4 -0
- package/src/app/api/.well-known/agent-card/route.ts +46 -0
- package/src/app/api/a2a/route.ts +56 -0
- package/src/app/api/a2a/tasks/[taskId]/status/route.ts +49 -0
- package/src/app/api/chats/[id]/deploy/route.ts +2 -2
- package/src/app/api/openclaw/sync/route.ts +1 -1
- package/src/app/api/swarmfeed/channels/route.ts +14 -0
- package/src/app/api/swarmfeed/posts/route.ts +60 -0
- package/src/app/api/swarmfeed/route.ts +37 -0
- package/src/app/protocols/builder/[templateId]/page.tsx +93 -0
- package/src/app/protocols/page.tsx +16 -7
- package/src/app/swarmfeed/page.tsx +7 -0
- package/src/cli/index.js +19 -0
- package/src/cli/spec.js +8 -0
- package/src/components/agents/agent-avatar.tsx +2 -5
- package/src/components/agents/agent-sheet.tsx +10 -0
- package/src/components/auth/access-key-gate.tsx +25 -0
- package/src/components/layout/sidebar-rail.tsx +52 -0
- package/src/components/protocols/builder/edge-editor.tsx +43 -0
- package/src/components/protocols/builder/edge-types/branch-edge.tsx +33 -0
- package/src/components/protocols/builder/edge-types/default-edge.tsx +18 -0
- package/src/components/protocols/builder/edge-types/index.ts +3 -0
- package/src/components/protocols/builder/edge-types/loop-edge.tsx +19 -0
- package/src/components/protocols/builder/node-inspector.tsx +227 -0
- package/src/components/protocols/builder/node-palette.tsx +97 -0
- package/src/components/protocols/builder/node-types/branch-node.tsx +34 -0
- package/src/components/protocols/builder/node-types/complete-node.tsx +17 -0
- package/src/components/protocols/builder/node-types/for-each-node.tsx +21 -0
- package/src/components/protocols/builder/node-types/index.ts +9 -0
- package/src/components/protocols/builder/node-types/join-node.tsx +18 -0
- package/src/components/protocols/builder/node-types/loop-node.tsx +22 -0
- package/src/components/protocols/builder/node-types/parallel-node.tsx +31 -0
- package/src/components/protocols/builder/node-types/phase-node.tsx +52 -0
- package/src/components/protocols/builder/node-types/subflow-node.tsx +23 -0
- package/src/components/protocols/builder/node-types/swarm-node.tsx +26 -0
- package/src/components/protocols/builder/protocol-builder-canvas.tsx +184 -0
- package/src/components/protocols/builder/run-overlay.tsx +29 -0
- package/src/components/protocols/builder/template-gallery.tsx +53 -0
- package/src/components/protocols/builder/validation-panel.tsx +57 -0
- package/src/components/skills/skills-workspace.tsx +1 -9
- package/src/features/protocols/builder/hooks/index.ts +2 -0
- package/src/features/protocols/builder/hooks/use-canvas-validation.ts +14 -0
- package/src/features/protocols/builder/hooks/use-run-overlay.ts +39 -0
- package/src/features/protocols/builder/hooks/use-template-sync.ts +45 -0
- package/src/features/protocols/builder/protocol-builder-store.ts +233 -0
- package/src/features/protocols/builder/utils/node-position-layout.ts +41 -0
- package/src/features/protocols/builder/utils/nodes-to-template.test.ts +179 -0
- package/src/features/protocols/builder/utils/nodes-to-template.ts +49 -0
- package/src/features/protocols/builder/utils/template-to-nodes.test.ts +314 -0
- package/src/features/protocols/builder/utils/template-to-nodes.ts +169 -0
- package/src/features/protocols/builder/validators/dag-validator.test.ts +150 -0
- package/src/features/protocols/builder/validators/dag-validator.ts +119 -0
- package/src/features/swarmfeed/agent-social-settings.tsx +277 -0
- package/src/features/swarmfeed/compose-post.tsx +139 -0
- package/src/features/swarmfeed/feed-page.tsx +136 -0
- package/src/features/swarmfeed/post-card.tsx +114 -0
- package/src/features/swarmfeed/queries.ts +28 -0
- package/src/lib/a2a/agent-card.ts +61 -0
- package/src/lib/a2a/auth.ts +54 -0
- package/src/lib/a2a/client.ts +133 -0
- package/src/lib/a2a/discovery.ts +116 -0
- package/src/lib/a2a/handlers.ts +176 -0
- package/src/lib/a2a/json-rpc-router.ts +38 -0
- package/src/lib/a2a/types.ts +95 -0
- package/src/lib/app/navigation.ts +1 -0
- package/src/lib/app/view-constants.ts +9 -1
- package/src/lib/providers/anthropic.ts +111 -107
- package/src/lib/providers/openai.ts +146 -142
- package/src/lib/server/agents/main-agent-loop.test.ts +94 -0
- package/src/lib/server/agents/main-agent-loop.ts +377 -41
- package/src/lib/server/chat-execution/chat-execution.ts +12 -7
- package/src/lib/server/extensions.ts +11 -0
- package/src/lib/server/openclaw/sync.ts +4 -4
- package/src/lib/server/protocols/protocol-a2a-delegate.ts +135 -0
- package/src/lib/server/protocols/protocol-normalization.ts +1 -0
- package/src/lib/server/protocols/protocol-step-helpers.test.ts +1 -1
- package/src/lib/server/protocols/protocol-step-helpers.ts +1 -0
- package/src/lib/server/protocols/protocol-step-processors.ts +2 -0
- package/src/lib/server/protocols/protocol-types.ts +1 -0
- package/src/lib/server/session-tools/delegate.ts +151 -77
- package/src/lib/server/storage-auth.ts +10 -2
- package/src/lib/server/storage-normalization.ts +11 -0
- package/src/lib/server/storage.ts +100 -0
- package/src/lib/server/working-state/service.test.ts +2 -3
- package/src/lib/server/working-state/service.ts +37 -6
- package/src/lib/swarmfeed-client.ts +157 -0
- package/src/lib/validation/schemas.ts +1 -1
- package/src/stores/slices/data-slice.ts +3 -0
- package/src/stores/use-approval-store.ts +4 -1
- package/src/types/agent.ts +31 -1
- package/src/types/index.ts +1 -0
- package/src/types/protocol.ts +19 -0
- package/src/types/session.ts +1 -1
- package/src/types/swarmfeed.ts +30 -0
|
@@ -244,15 +244,46 @@ export function syncWorkingStateFromMainLoopState(input: {
|
|
|
244
244
|
status?: WorkingStateStatus | null
|
|
245
245
|
nextAction?: string | null
|
|
246
246
|
planSteps?: string[]
|
|
247
|
+
completedPlanSteps?: string[]
|
|
247
248
|
blockers?: Array<{ summary: string; kind?: WorkingBlocker['kind'] | null }>
|
|
248
249
|
facts?: string[]
|
|
249
250
|
}): SessionWorkingState {
|
|
250
|
-
const planSteps =
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
const planSteps = (() => {
|
|
252
|
+
const activeSteps = Array.isArray(input.planSteps)
|
|
253
|
+
? input.planSteps
|
|
254
|
+
.map((step) => cleanText(step, 240))
|
|
255
|
+
.filter((step): step is string => Boolean(step))
|
|
256
|
+
: []
|
|
257
|
+
const completedSteps = Array.isArray(input.completedPlanSteps)
|
|
258
|
+
? input.completedPlanSteps
|
|
259
|
+
.map((step) => cleanText(step, 240))
|
|
260
|
+
.filter((step): step is string => Boolean(step))
|
|
261
|
+
: []
|
|
262
|
+
const out: WorkingPlanStepPatch[] = []
|
|
263
|
+
const seen = new Set<string>()
|
|
264
|
+
|
|
265
|
+
for (const [index, step] of activeSteps.entries()) {
|
|
266
|
+
const key = step.toLowerCase()
|
|
267
|
+
if (seen.has(key)) continue
|
|
268
|
+
seen.add(key)
|
|
269
|
+
out.push({
|
|
270
|
+
text: step,
|
|
271
|
+
status: index === 0 && input.status !== 'completed' ? 'active' : 'resolved',
|
|
272
|
+
} satisfies WorkingPlanStepPatch)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (const step of completedSteps) {
|
|
276
|
+
const key = step.toLowerCase()
|
|
277
|
+
if (seen.has(key)) continue
|
|
278
|
+
seen.add(key)
|
|
279
|
+
out.push({
|
|
280
|
+
text: step,
|
|
281
|
+
status: 'resolved',
|
|
282
|
+
} satisfies WorkingPlanStepPatch)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return out.length > 0 ? out : undefined
|
|
286
|
+
})()
|
|
256
287
|
return applyWorkingStatePatch(input.sessionId, {
|
|
257
288
|
objective: cleanMultiline(input.goal, 900) || undefined,
|
|
258
289
|
summary: cleanMultiline(input.summary, 600) || undefined,
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { hmrSingleton } from '@/lib/shared-utils'
|
|
2
|
+
import type { SwarmFeedPost, SwarmFeedChannel, CreatePostInput, FeedType } from '@/types/swarmfeed'
|
|
3
|
+
|
|
4
|
+
interface SwarmFeedConfig {
|
|
5
|
+
apiUrl: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const config = hmrSingleton<SwarmFeedConfig>('swarmfeed_config', () => ({
|
|
9
|
+
apiUrl: process.env.SWARMFEED_API_URL || 'http://localhost:3700',
|
|
10
|
+
}))
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Internal fetch helper for SwarmFeed API.
|
|
14
|
+
* @param agentApiKey - Per-agent API key (sf_live_*) for authenticated requests. Omit for public endpoints.
|
|
15
|
+
*/
|
|
16
|
+
async function sfFetch<T>(path: string, agentApiKey?: string, init?: RequestInit): Promise<T> {
|
|
17
|
+
const url = `${config.apiUrl}${path}`
|
|
18
|
+
const headers: Record<string, string> = {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
...(agentApiKey ? { Authorization: `Bearer ${agentApiKey}` } : {}),
|
|
21
|
+
}
|
|
22
|
+
const res = await fetch(url, {
|
|
23
|
+
...init,
|
|
24
|
+
headers: { ...headers, ...(init?.headers as Record<string, string> | undefined) },
|
|
25
|
+
})
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
const text = await res.text().catch(() => 'Unknown error')
|
|
28
|
+
throw new Error(`SwarmFeed API error ${res.status}: ${text}`)
|
|
29
|
+
}
|
|
30
|
+
return res.json() as Promise<T>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// --- Feed (public, no auth needed) ---
|
|
34
|
+
|
|
35
|
+
const FEED_TYPE_URL: Record<FeedType, string> = {
|
|
36
|
+
for_you: 'for-you',
|
|
37
|
+
following: 'following',
|
|
38
|
+
channel: 'channel',
|
|
39
|
+
trending: 'trending',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function getFeed(
|
|
43
|
+
type: FeedType,
|
|
44
|
+
params?: { channelId?: string; cursor?: string; limit?: number },
|
|
45
|
+
agentApiKey?: string,
|
|
46
|
+
): Promise<{ posts: SwarmFeedPost[]; nextCursor?: string }> {
|
|
47
|
+
const urlSegment = FEED_TYPE_URL[type] ?? type
|
|
48
|
+
|
|
49
|
+
// Channel feed uses path param: /feed/channel/:channelId
|
|
50
|
+
if (type === 'channel' && params?.channelId) {
|
|
51
|
+
const searchParams = new URLSearchParams()
|
|
52
|
+
if (params.cursor) searchParams.set('cursor', params.cursor)
|
|
53
|
+
if (params.limit) searchParams.set('limit', String(params.limit))
|
|
54
|
+
const qs = searchParams.toString()
|
|
55
|
+
return sfFetch(`/api/v1/feed/channel/${params.channelId}${qs ? `?${qs}` : ''}`, agentApiKey)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const searchParams = new URLSearchParams()
|
|
59
|
+
if (params?.cursor) searchParams.set('cursor', params.cursor)
|
|
60
|
+
if (params?.limit) searchParams.set('limit', String(params.limit))
|
|
61
|
+
const qs = searchParams.toString()
|
|
62
|
+
return sfFetch(`/api/v1/feed/${urlSegment}${qs ? `?${qs}` : ''}`, agentApiKey)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// --- Posts (auth required for writes) ---
|
|
66
|
+
|
|
67
|
+
export async function createPost(agentApiKey: string, input: CreatePostInput): Promise<SwarmFeedPost> {
|
|
68
|
+
return sfFetch('/api/v1/posts', agentApiKey, {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
content: input.content,
|
|
72
|
+
channelId: input.channelId,
|
|
73
|
+
parentId: input.parentId,
|
|
74
|
+
}),
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// --- Reactions (auth required) ---
|
|
79
|
+
|
|
80
|
+
export async function likePost(agentApiKey: string, postId: string): Promise<unknown> {
|
|
81
|
+
return sfFetch(`/api/v1/posts/${postId}/like`, agentApiKey, {
|
|
82
|
+
method: 'POST',
|
|
83
|
+
body: JSON.stringify({ reactionType: 'like' }),
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function repostPost(agentApiKey: string, postId: string): Promise<unknown> {
|
|
88
|
+
return sfFetch(`/api/v1/posts/${postId}/like`, agentApiKey, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
body: JSON.stringify({ reactionType: 'repost' }),
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// --- Channels (public reads) ---
|
|
95
|
+
|
|
96
|
+
export async function getChannels(): Promise<SwarmFeedChannel[]> {
|
|
97
|
+
const result = await sfFetch<{ channels: SwarmFeedChannel[] }>('/api/v1/channels')
|
|
98
|
+
return result.channels
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// --- Agent Registration ---
|
|
102
|
+
|
|
103
|
+
interface RegisterResult {
|
|
104
|
+
agentId: string
|
|
105
|
+
apiKey: string
|
|
106
|
+
challenge: string
|
|
107
|
+
challengeExpiresAt: string
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Register a SwarmClaw agent on SwarmFeed.
|
|
112
|
+
* Generates an Ed25519 keypair, registers, verifies, and returns the API key.
|
|
113
|
+
*/
|
|
114
|
+
export async function registerAgent(agent: {
|
|
115
|
+
name: string
|
|
116
|
+
description?: string
|
|
117
|
+
framework?: string
|
|
118
|
+
model?: string
|
|
119
|
+
avatar?: string
|
|
120
|
+
bio?: string
|
|
121
|
+
}): Promise<{ agentId: string; apiKey: string }> {
|
|
122
|
+
// Dynamic import tweetnacl (available in SwarmClaw's deps)
|
|
123
|
+
const naclModule = await import('tweetnacl')
|
|
124
|
+
const nacl = naclModule.default ?? naclModule
|
|
125
|
+
const keypair = nacl.sign.keyPair()
|
|
126
|
+
const publicKeyHex = Buffer.from(keypair.publicKey).toString('hex')
|
|
127
|
+
|
|
128
|
+
// Step 1: Register
|
|
129
|
+
const reg = await sfFetch<RegisterResult>('/api/v1/register', undefined, {
|
|
130
|
+
method: 'POST',
|
|
131
|
+
body: JSON.stringify({
|
|
132
|
+
publicKey: publicKeyHex,
|
|
133
|
+
name: agent.name,
|
|
134
|
+
description: agent.description,
|
|
135
|
+
framework: agent.framework,
|
|
136
|
+
modelName: agent.model,
|
|
137
|
+
avatarUrl: agent.avatar,
|
|
138
|
+
bio: agent.bio,
|
|
139
|
+
}),
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
// Step 2: Sign the challenge and verify
|
|
143
|
+
const messageBytes = new TextEncoder().encode(reg.challenge)
|
|
144
|
+
const signature = nacl.sign.detached(messageBytes, keypair.secretKey)
|
|
145
|
+
const signatureHex = Buffer.from(signature).toString('hex')
|
|
146
|
+
|
|
147
|
+
await sfFetch('/api/v1/register/verify', undefined, {
|
|
148
|
+
method: 'POST',
|
|
149
|
+
body: JSON.stringify({
|
|
150
|
+
publicKey: publicKeyHex,
|
|
151
|
+
challenge: reg.challenge,
|
|
152
|
+
signature: signatureHex,
|
|
153
|
+
}),
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
return { agentId: reg.agentId, apiKey: reg.apiKey }
|
|
157
|
+
}
|
|
@@ -147,7 +147,7 @@ export const ConnectorCreateSchema = z.object({
|
|
|
147
147
|
export const ExternalAgentRegisterSchema = z.object({
|
|
148
148
|
id: z.string().optional(),
|
|
149
149
|
name: z.string().min(1, 'External agent name is required'),
|
|
150
|
-
sourceType: z.enum(['codex', 'claude', 'opencode', 'openclaw', 'custom']).default('custom'),
|
|
150
|
+
sourceType: z.enum(['codex', 'claude', 'opencode', 'openclaw', 'custom', 'a2a']).default('custom'),
|
|
151
151
|
status: z.enum(['online', 'idle', 'offline', 'stale']).optional().default('online'),
|
|
152
152
|
provider: z.string().nullable().optional().default(null),
|
|
153
153
|
model: z.string().nullable().optional().default(null),
|
|
@@ -159,6 +159,7 @@ export const createDataSlice: StateCreator<AppState, [], [], DataSlice> = (set,
|
|
|
159
159
|
const notifications = get().notifications.map((n) =>
|
|
160
160
|
n.id === id ? { ...n, read: true } : n,
|
|
161
161
|
)
|
|
162
|
+
invalidateFingerprint('notifications')
|
|
162
163
|
set({
|
|
163
164
|
notifications,
|
|
164
165
|
unreadNotificationCount: notifications.filter((n) => !n.read).length,
|
|
@@ -174,6 +175,7 @@ export const createDataSlice: StateCreator<AppState, [], [], DataSlice> = (set,
|
|
|
174
175
|
if (!unreadIds.length) return
|
|
175
176
|
const originalNotifications = get().notifications
|
|
176
177
|
const notifications = originalNotifications.map((n) => ({ ...n, read: true }))
|
|
178
|
+
invalidateFingerprint('notifications')
|
|
177
179
|
set({ notifications, unreadNotificationCount: 0 })
|
|
178
180
|
try {
|
|
179
181
|
await Promise.all(unreadIds.map((id) => api('PUT', `/notifications/${id}`, { read: true })))
|
|
@@ -185,6 +187,7 @@ export const createDataSlice: StateCreator<AppState, [], [], DataSlice> = (set,
|
|
|
185
187
|
clearReadNotifications: async () => {
|
|
186
188
|
const original = get().notifications
|
|
187
189
|
const kept = original.filter((n) => !n.read)
|
|
190
|
+
invalidateFingerprint('notifications')
|
|
188
191
|
set({ notifications: kept, unreadNotificationCount: kept.length })
|
|
189
192
|
try {
|
|
190
193
|
await api('DELETE', '/notifications')
|
|
@@ -4,6 +4,7 @@ import { create } from 'zustand'
|
|
|
4
4
|
import type { PendingExecApproval, ExecApprovalDecision } from '@/types'
|
|
5
5
|
import { api } from '@/lib/app/api-client'
|
|
6
6
|
import { errorMessage } from '@/lib/shared-utils'
|
|
7
|
+
import { setIfChanged, invalidateFingerprint } from './set-if-changed'
|
|
7
8
|
|
|
8
9
|
interface ApprovalState {
|
|
9
10
|
approvals: Record<string, PendingExecApproval>
|
|
@@ -20,10 +21,12 @@ export const useApprovalStore = create<ApprovalState>((set) => ({
|
|
|
20
21
|
resolvedIds: new Set<string>(),
|
|
21
22
|
|
|
22
23
|
addApproval: (approval) => {
|
|
24
|
+
invalidateFingerprint('approvals')
|
|
23
25
|
set((s) => ({ approvals: { ...s.approvals, [approval.id]: approval } }))
|
|
24
26
|
},
|
|
25
27
|
|
|
26
28
|
removeApproval: (id) => {
|
|
29
|
+
invalidateFingerprint('approvals')
|
|
27
30
|
set((s) => {
|
|
28
31
|
const next = { ...s.approvals }
|
|
29
32
|
delete next[id]
|
|
@@ -91,7 +94,7 @@ export const useApprovalStore = create<ApprovalState>((set) => ({
|
|
|
91
94
|
const result = await api<PendingExecApproval[]>('GET', '/openclaw/approvals')
|
|
92
95
|
const approvals: Record<string, PendingExecApproval> = {}
|
|
93
96
|
for (const a of result) approvals[a.id] = a
|
|
94
|
-
set
|
|
97
|
+
setIfChanged<ApprovalState>(set, 'approvals', approvals)
|
|
95
98
|
} catch {
|
|
96
99
|
// ignore — gateway may be offline
|
|
97
100
|
}
|
package/src/types/agent.ts
CHANGED
|
@@ -3,6 +3,17 @@ import type { SessionResetMode, IdentityContinuityState } from './session'
|
|
|
3
3
|
import type { SkillAllowlistMode } from './skill'
|
|
4
4
|
import type { DreamConfig } from './dream'
|
|
5
5
|
|
|
6
|
+
// --- SwarmFeed Heartbeat ---
|
|
7
|
+
|
|
8
|
+
export interface SwarmFeedHeartbeatConfig {
|
|
9
|
+
enabled: boolean
|
|
10
|
+
browseFeed: boolean
|
|
11
|
+
postFrequency: 'every_cycle' | 'daily' | 'on_task_completion' | 'manual_only'
|
|
12
|
+
autoReply: boolean
|
|
13
|
+
autoFollow: boolean
|
|
14
|
+
channelsToMonitor: string[]
|
|
15
|
+
}
|
|
16
|
+
|
|
6
17
|
// --- Agent / Delegation ---
|
|
7
18
|
|
|
8
19
|
export type AgentRole = 'worker' | 'coordinator'
|
|
@@ -180,6 +191,18 @@ export interface Agent {
|
|
|
180
191
|
orchestratorLastWakeAt?: number | null
|
|
181
192
|
orchestratorCycleCount?: number
|
|
182
193
|
|
|
194
|
+
// SwarmFeed (social network integration)
|
|
195
|
+
swarmfeedEnabled?: boolean
|
|
196
|
+
swarmfeedJoinedAt?: number | null
|
|
197
|
+
swarmfeedBio?: string | null
|
|
198
|
+
swarmfeedPinnedPostId?: string | null
|
|
199
|
+
swarmfeedAutoPost?: boolean
|
|
200
|
+
swarmfeedAutoPostChannels?: string[]
|
|
201
|
+
swarmfeedApiKey?: string | null
|
|
202
|
+
swarmfeedAgentId?: string | null
|
|
203
|
+
origin?: 'swarmdock' | 'swarmfeed' | 'swarmclaw' | 'external'
|
|
204
|
+
swarmfeedHeartbeat?: SwarmFeedHeartbeatConfig | null
|
|
205
|
+
|
|
183
206
|
createdAt: number
|
|
184
207
|
updatedAt: number
|
|
185
208
|
}
|
|
@@ -246,7 +269,7 @@ export interface AgentPackManifest {
|
|
|
246
269
|
|
|
247
270
|
// --- External Agents ---
|
|
248
271
|
|
|
249
|
-
export type ExternalAgentSourceType = 'codex' | 'claude' | 'opencode' | 'openclaw' | 'custom'
|
|
272
|
+
export type ExternalAgentSourceType = 'codex' | 'claude' | 'opencode' | 'openclaw' | 'custom' | 'a2a'
|
|
250
273
|
export type ExternalAgentStatus = 'online' | 'idle' | 'offline' | 'stale'
|
|
251
274
|
|
|
252
275
|
export interface ExternalAgentRuntime {
|
|
@@ -274,6 +297,13 @@ export interface ExternalAgentRuntime {
|
|
|
274
297
|
outputTokens?: number
|
|
275
298
|
totalTokens?: number
|
|
276
299
|
} | null
|
|
300
|
+
a2aCard?: {
|
|
301
|
+
protocolVersion?: string | null
|
|
302
|
+
apiEndpoint?: string | null
|
|
303
|
+
capabilities?: Array<{ name: string; methods?: string[]; description?: string | null }>
|
|
304
|
+
supportsStreaming?: boolean
|
|
305
|
+
supportsAsync?: boolean
|
|
306
|
+
} | null
|
|
277
307
|
lastHeartbeatAt?: number | null
|
|
278
308
|
lastSeenAt?: number | null
|
|
279
309
|
createdAt: number
|
package/src/types/index.ts
CHANGED
package/src/types/protocol.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type ProtocolPhaseKind =
|
|
|
16
16
|
| 'wait'
|
|
17
17
|
| 'dispatch_task'
|
|
18
18
|
| 'dispatch_delegation'
|
|
19
|
+
| 'a2a_delegate'
|
|
19
20
|
|
|
20
21
|
export interface ProtocolPhaseDefinition {
|
|
21
22
|
id: string
|
|
@@ -26,6 +27,15 @@ export interface ProtocolPhaseDefinition {
|
|
|
26
27
|
completionCriteria?: string | null
|
|
27
28
|
taskConfig?: { agentId?: string; title: string; description: string } | null
|
|
28
29
|
delegationConfig?: { agentId: string; message: string } | null
|
|
30
|
+
a2aDelegateConfig?: {
|
|
31
|
+
targetUrl?: string | null
|
|
32
|
+
targetExternalAgentId?: string | null
|
|
33
|
+
taskName: string
|
|
34
|
+
taskMessage: string
|
|
35
|
+
timeoutMs?: number | null
|
|
36
|
+
credentialId?: string | null
|
|
37
|
+
onFailure?: 'fail' | 'advance_with_warning'
|
|
38
|
+
} | null
|
|
29
39
|
}
|
|
30
40
|
|
|
31
41
|
export type ProtocolConditionDefinition =
|
|
@@ -90,6 +100,15 @@ export interface ProtocolStepDefinition {
|
|
|
90
100
|
completionCriteria?: string | null
|
|
91
101
|
taskConfig?: { agentId?: string; title: string; description: string } | null
|
|
92
102
|
delegationConfig?: { agentId: string; message: string } | null
|
|
103
|
+
a2aDelegateConfig?: {
|
|
104
|
+
targetUrl?: string | null
|
|
105
|
+
targetExternalAgentId?: string | null
|
|
106
|
+
taskName: string
|
|
107
|
+
taskMessage: string
|
|
108
|
+
timeoutMs?: number | null
|
|
109
|
+
credentialId?: string | null
|
|
110
|
+
onFailure?: 'fail' | 'advance_with_warning'
|
|
111
|
+
} | null
|
|
93
112
|
nextStepId?: string | null
|
|
94
113
|
branchCases?: ProtocolBranchCase[]
|
|
95
114
|
defaultNextStepId?: string | null
|
package/src/types/session.ts
CHANGED
|
@@ -214,4 +214,4 @@ export type SessionTool =
|
|
|
214
214
|
| 'crawl'
|
|
215
215
|
|
|
216
216
|
export type SessionType = 'human'
|
|
217
|
-
export type AppView = 'home' | 'agents' | 'org_chart' | 'inbox' | 'chatrooms' | 'protocols' | 'schedules' | 'memory' | 'tasks' | 'secrets' | 'wallets' | 'providers' | 'skills' | 'connectors' | 'webhooks' | 'mcp_servers' | 'knowledge' | 'extensions' | 'usage' | 'runs' | 'autonomy' | 'logs' | 'settings' | 'projects' | 'activity'
|
|
217
|
+
export type AppView = 'home' | 'agents' | 'org_chart' | 'inbox' | 'chatrooms' | 'protocols' | 'schedules' | 'memory' | 'tasks' | 'secrets' | 'wallets' | 'providers' | 'skills' | 'connectors' | 'webhooks' | 'mcp_servers' | 'knowledge' | 'extensions' | 'usage' | 'runs' | 'autonomy' | 'logs' | 'settings' | 'projects' | 'activity' | 'swarmfeed'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface SwarmFeedPost {
|
|
2
|
+
id: string
|
|
3
|
+
agentId: string
|
|
4
|
+
content: string
|
|
5
|
+
channelId?: string
|
|
6
|
+
parentId?: string
|
|
7
|
+
likeCount: number
|
|
8
|
+
replyCount: number
|
|
9
|
+
repostCount: number
|
|
10
|
+
bookmarkCount: number
|
|
11
|
+
createdAt: string
|
|
12
|
+
agent?: { id: string; name: string; avatar?: string }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SwarmFeedChannel {
|
|
16
|
+
id: string
|
|
17
|
+
handle: string
|
|
18
|
+
displayName: string
|
|
19
|
+
description?: string
|
|
20
|
+
memberCount: number
|
|
21
|
+
postCount: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface CreatePostInput {
|
|
25
|
+
content: string
|
|
26
|
+
channelId?: string
|
|
27
|
+
parentId?: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type FeedType = 'for_you' | 'following' | 'channel' | 'trending'
|