@swarmclawai/swarmclaw 1.6.0 → 1.7.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 +20 -0
- package/package.json +3 -3
- package/src/app/.well-known/agent-card.json/route.ts +15 -0
- package/src/app/api/.well-known/agent-card/route.ts +6 -37
- package/src/app/home/page.tsx +10 -19
- package/src/components/auth/setup-wizard/index.tsx +2 -6
- package/src/components/auth/setup-wizard/step-next.tsx +39 -46
- package/src/components/auth/setup-wizard/step-providers.tsx +142 -76
- package/src/components/auth/setup-wizard/types.ts +2 -5
- package/src/components/auth/setup-wizard/utils.test.ts +19 -0
- package/src/components/auth/setup-wizard/utils.ts +69 -0
- package/src/components/home/home-launchpad.tsx +100 -80
- package/src/lib/a2a/agent-card.test.ts +94 -0
- package/src/lib/a2a/agent-card.ts +41 -1
- package/src/lib/home-launchpad.test.ts +31 -1
- package/src/lib/home-launchpad.ts +58 -0
- package/src/lib/providers/cli-utils.test.ts +10 -0
- package/src/lib/providers/cli-utils.ts +31 -0
- package/src/lib/providers/generic-cli.test.ts +71 -0
- package/src/lib/providers/generic-cli.ts +138 -0
- package/src/lib/providers/index.ts +56 -1
- package/src/lib/providers/opencode-cli.test.ts +9 -0
- package/src/lib/providers/opencode-cli.ts +5 -1
- package/src/lib/server/missions/mission-templates.test.ts +17 -0
- package/src/lib/server/missions/mission-templates.ts +69 -0
- package/src/lib/server/protocols/protocol-service.test.ts +25 -0
- package/src/lib/server/protocols/protocol-templates.ts +48 -0
- package/src/lib/strip-internal-metadata.test.ts +23 -0
- package/src/lib/strip-internal-metadata.ts +136 -7
- package/src/types/provider.ts +1 -1
|
@@ -9,27 +9,156 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Importable from both client and server code.
|
|
11
11
|
*/
|
|
12
|
+
import { z } from 'zod'
|
|
12
13
|
|
|
13
14
|
// ---------------------------------------------------------------------------
|
|
14
15
|
// Classification JSON
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
|
|
17
18
|
const INTERNAL_JSON_KEYS = [
|
|
18
|
-
'
|
|
19
|
-
'
|
|
19
|
+
'factsUpsert', 'artifactsUpsert', 'planSteps', 'decisionsAppend',
|
|
20
|
+
'blockersUpsert', 'questionsUpsert', 'hypothesesUpsert', 'supersedeIds',
|
|
21
|
+
'taskIntent', 'isLightweightDirectChat', 'isDeliverableTask', 'quality_score',
|
|
22
|
+
'isBroadGoal', 'hasHumanSignals', 'explicitToolRequests', 'isResearchSynthesis',
|
|
23
|
+
'confidence', 'isIncomplete',
|
|
20
24
|
]
|
|
21
25
|
|
|
22
26
|
export const INTERNAL_KEY_RE = new RegExp(`"(?:${INTERNAL_JSON_KEYS.join('|')})"`)
|
|
23
27
|
|
|
28
|
+
const WorkingStatePatchLikeSchema = z.object({
|
|
29
|
+
factsUpsert: z.array(z.unknown()).optional(),
|
|
30
|
+
artifactsUpsert: z.array(z.unknown()).optional(),
|
|
31
|
+
planSteps: z.array(z.unknown()).optional(),
|
|
32
|
+
decisionsAppend: z.array(z.unknown()).optional(),
|
|
33
|
+
blockersUpsert: z.array(z.unknown()).optional(),
|
|
34
|
+
questionsUpsert: z.array(z.unknown()).optional(),
|
|
35
|
+
hypothesesUpsert: z.array(z.unknown()).optional(),
|
|
36
|
+
supersedeIds: z.array(z.unknown()).optional(),
|
|
37
|
+
}).passthrough()
|
|
38
|
+
|
|
39
|
+
const MessageClassificationLikeSchema = z.object({
|
|
40
|
+
taskIntent: z.string().optional(),
|
|
41
|
+
isLightweightDirectChat: z.boolean().optional(),
|
|
42
|
+
isDeliverableTask: z.boolean().optional(),
|
|
43
|
+
isBroadGoal: z.boolean().optional(),
|
|
44
|
+
hasHumanSignals: z.boolean().optional(),
|
|
45
|
+
explicitToolRequests: z.array(z.unknown()).optional(),
|
|
46
|
+
isResearchSynthesis: z.boolean().optional(),
|
|
47
|
+
confidence: z.number().optional(),
|
|
48
|
+
}).passthrough()
|
|
49
|
+
|
|
50
|
+
const ResponseCompletenessLikeSchema = z.object({
|
|
51
|
+
isIncomplete: z.boolean(),
|
|
52
|
+
}).passthrough()
|
|
53
|
+
|
|
54
|
+
const QualityScoreLikeSchema = z.object({
|
|
55
|
+
quality_score: z.number(),
|
|
56
|
+
quality_reasoning: z.string().optional(),
|
|
57
|
+
}).passthrough()
|
|
58
|
+
|
|
59
|
+
interface InternalPayloadRule {
|
|
60
|
+
schema: z.ZodType<unknown>
|
|
61
|
+
distinctiveKeys: string[]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const INTERNAL_PAYLOAD_RULES: InternalPayloadRule[] = [
|
|
65
|
+
{
|
|
66
|
+
schema: WorkingStatePatchLikeSchema,
|
|
67
|
+
distinctiveKeys: [
|
|
68
|
+
'factsUpsert',
|
|
69
|
+
'artifactsUpsert',
|
|
70
|
+
'planSteps',
|
|
71
|
+
'decisionsAppend',
|
|
72
|
+
'blockersUpsert',
|
|
73
|
+
'questionsUpsert',
|
|
74
|
+
'hypothesesUpsert',
|
|
75
|
+
'supersedeIds',
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
schema: MessageClassificationLikeSchema,
|
|
80
|
+
distinctiveKeys: [
|
|
81
|
+
'isLightweightDirectChat',
|
|
82
|
+
'isDeliverableTask',
|
|
83
|
+
'isBroadGoal',
|
|
84
|
+
'hasHumanSignals',
|
|
85
|
+
'explicitToolRequests',
|
|
86
|
+
'isResearchSynthesis',
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
schema: ResponseCompletenessLikeSchema,
|
|
91
|
+
distinctiveKeys: ['isIncomplete'],
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
schema: QualityScoreLikeSchema,
|
|
95
|
+
distinctiveKeys: ['quality_score'],
|
|
96
|
+
},
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
function objectIsInternalMetadata(obj: Record<string, unknown>): boolean {
|
|
100
|
+
for (const { schema, distinctiveKeys } of INTERNAL_PAYLOAD_RULES) {
|
|
101
|
+
if (!distinctiveKeys.some((key) => key in obj)) continue
|
|
102
|
+
if (schema.safeParse(obj).success) return true
|
|
103
|
+
}
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function findBalancedJsonObjectEnd(text: string, start: number): number {
|
|
108
|
+
if (text.charAt(start) !== '{') return -1
|
|
109
|
+
let depth = 0
|
|
110
|
+
let inString = false
|
|
111
|
+
let escaped = false
|
|
112
|
+
for (let i = start; i < text.length; i += 1) {
|
|
113
|
+
const c = text.charAt(i)
|
|
114
|
+
if (inString) {
|
|
115
|
+
if (escaped) escaped = false
|
|
116
|
+
else if (c === '\\') escaped = true
|
|
117
|
+
else if (c === '"') inString = false
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
if (c === '"') {
|
|
121
|
+
inString = true
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
if (c === '{') depth += 1
|
|
125
|
+
else if (c === '}') {
|
|
126
|
+
depth -= 1
|
|
127
|
+
if (depth === 0) return i + 1
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return -1
|
|
131
|
+
}
|
|
132
|
+
|
|
24
133
|
/**
|
|
25
134
|
* Remove top-level `{ ... }` blocks that contain known internal classification keys.
|
|
26
|
-
* Handles multi-line JSON. Only strips blocks where at least one
|
|
135
|
+
* Handles nested and multi-line JSON. Only strips blocks where at least one
|
|
136
|
+
* distinctive internal key is present and the payload passes schema validation.
|
|
27
137
|
*/
|
|
28
138
|
export function stripInternalJson(text: string): string {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
139
|
+
let out = text || ''
|
|
140
|
+
for (let guard = 0; guard < 32; guard += 1) {
|
|
141
|
+
let removed = false
|
|
142
|
+
for (let i = 0; i < out.length; i += 1) {
|
|
143
|
+
if (out.charAt(i) !== '{') continue
|
|
144
|
+
const end = findBalancedJsonObjectEnd(out, i)
|
|
145
|
+
if (end <= i) continue
|
|
146
|
+
const candidate = out.slice(i, end)
|
|
147
|
+
let parsed: unknown
|
|
148
|
+
try {
|
|
149
|
+
parsed = JSON.parse(candidate)
|
|
150
|
+
} catch {
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue
|
|
154
|
+
if (!objectIsInternalMetadata(parsed as Record<string, unknown>)) continue
|
|
155
|
+
out = (out.slice(0, i).replace(/\s+$/, '') + ' ' + out.slice(end).replace(/^\s+/, '')).trim()
|
|
156
|
+
removed = true
|
|
157
|
+
break
|
|
158
|
+
}
|
|
159
|
+
if (!removed) break
|
|
160
|
+
}
|
|
161
|
+
return out
|
|
33
162
|
}
|
|
34
163
|
|
|
35
164
|
// ---------------------------------------------------------------------------
|
package/src/types/provider.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type ProviderType = 'claude-cli' | 'codex-cli' | 'opencode-cli' | 'opencode-web' | 'gemini-cli' | 'copilot-cli' | 'droid-cli' | 'cursor-cli' | 'qwen-code-cli' | 'goose' | 'openai' | 'openrouter' | 'ollama' | 'anthropic' | 'openclaw' | 'hermes' | 'google' | 'deepseek' | 'groq' | 'together' | 'mistral' | 'xai' | 'fireworks' | 'nebius' | 'deepinfra'
|
|
1
|
+
export type ProviderType = 'claude-cli' | 'codex-cli' | 'opencode-cli' | 'opencode-web' | 'gemini-cli' | 'copilot-cli' | 'droid-cli' | 'cursor-cli' | 'qwen-code-cli' | 'goose' | 'aider-cli' | 'amp-cli' | 'augment-cli' | 'adal-cli' | 'bob-cli' | 'cline-cli' | 'codebuddy-cli' | 'command-code-cli' | 'continue-cli' | 'cortex-cli' | 'crush-cli' | 'deepagents-cli' | 'firebender-cli' | 'iflow-cli' | 'junie-cli' | 'kilo-code-cli' | 'kimi-cli' | 'kode-cli' | 'mcpjam-cli' | 'mistral-vibe-cli' | 'mux-cli' | 'neovate-cli' | 'openhands-cli' | 'pochi-cli' | 'qoder-cli' | 'replit-cli' | 'roo-code-cli' | 'trae-cn-cli' | 'warp-cli' | 'windsurf-cli' | 'zencoder-cli' | 'openai' | 'openrouter' | 'ollama' | 'anthropic' | 'openclaw' | 'hermes' | 'google' | 'deepseek' | 'groq' | 'together' | 'mistral' | 'xai' | 'fireworks' | 'nebius' | 'deepinfra'
|
|
2
2
|
export type ProviderId = ProviderType | (string & {})
|
|
3
3
|
|
|
4
4
|
export interface ProviderInfo {
|