@swarmclawai/swarmclaw 1.9.35 → 1.9.38

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.
Files changed (37) hide show
  1. package/README.md +53 -1
  2. package/package.json +3 -3
  3. package/src/app/api/chats/[id]/context-status/route.ts +2 -0
  4. package/src/app/api/chats/context-status-route.test.ts +59 -0
  5. package/src/app/api/openclaw/history/route.ts +11 -6
  6. package/src/app/api/preview-server/route.ts +20 -12
  7. package/src/app/api/search/route.test.ts +63 -0
  8. package/src/app/api/search/route.ts +3 -2
  9. package/src/app/api/settings/route.ts +5 -1
  10. package/src/app/api/settings/settings-route.test.ts +38 -0
  11. package/src/app/api/setup/check-provider/route.test.ts +12 -0
  12. package/src/app/api/setup/check-provider/route.ts +6 -0
  13. package/src/app/api/usage/live/route.ts +2 -2
  14. package/src/app/globals.css +158 -0
  15. package/src/app/layout.tsx +12 -9
  16. package/src/app/protocols/builder/[templateId]/page.tsx +5 -5
  17. package/src/components/layout/dashboard-shell.tsx +9 -0
  18. package/src/components/protocols/builder/protocol-builder-canvas.tsx +106 -15
  19. package/src/components/providers/theme-provider.tsx +16 -0
  20. package/src/features/protocols/builder/hooks/use-template-sync.ts +5 -0
  21. package/src/features/protocols/builder/protocol-builder-store.ts +4 -4
  22. package/src/features/protocols/builder/utils/builder-template-access.test.ts +30 -0
  23. package/src/features/protocols/builder/utils/builder-template-access.ts +5 -0
  24. package/src/lib/providers/index.ts +23 -0
  25. package/src/lib/server/context-manager.ts +4 -0
  26. package/src/lib/server/messages/message-repository.test.ts +122 -0
  27. package/src/lib/server/messages/message-repository.ts +67 -11
  28. package/src/lib/server/openrouter-model-context.test.ts +205 -0
  29. package/src/lib/server/openrouter-model-context.ts +169 -0
  30. package/src/lib/server/provider-health.ts +1 -0
  31. package/src/lib/server/runtime/devserver-launch.ts +7 -4
  32. package/src/lib/setup-defaults.test.ts +10 -1
  33. package/src/lib/setup-defaults.ts +20 -0
  34. package/src/lib/theme-mode.ts +5 -0
  35. package/src/types/app-settings.ts +2 -0
  36. package/src/types/provider.ts +1 -1
  37. package/src/views/settings/section-theme.tsx +41 -1
@@ -86,6 +86,19 @@ export const SETUP_PROVIDERS: SetupProviderOption[] = [
86
86
  icon: 'R',
87
87
  modelLibraryUrl: 'https://openrouter.ai/models',
88
88
  },
89
+ {
90
+ id: 'tokenmix',
91
+ name: 'TokenMix',
92
+ description: 'One OpenAI-compatible API relay for Claude, OpenAI, Gemini, DeepSeek, Qwen, and other hosted models.',
93
+ requiresKey: true,
94
+ supportsEndpoint: false,
95
+ defaultEndpoint: 'https://api.tokenmix.ai/v1',
96
+ keyUrl: 'https://tokenmix.ai',
97
+ keyLabel: 'tokenmix.ai',
98
+ badge: 'Catalog',
99
+ icon: 'T',
100
+ modelLibraryUrl: 'https://tokenmix.ai/models',
101
+ },
89
102
  {
90
103
  id: 'openclaw',
91
104
  name: 'OpenClaw',
@@ -781,6 +794,13 @@ export const DEFAULT_AGENTS = {
781
794
  model: 'anthropic/claude-sonnet-4.6',
782
795
  tools: STARTER_AGENT_TOOLS,
783
796
  },
797
+ tokenmix: {
798
+ name: 'TokenMix Agent',
799
+ description: 'A helpful assistant powered through TokenMix.',
800
+ systemPrompt: SWARMCLAW_ASSISTANT_PROMPT,
801
+ model: 'claude-sonnet-4-6',
802
+ tools: STARTER_AGENT_TOOLS,
803
+ },
784
804
  google: {
785
805
  name: 'Gemini',
786
806
  description: 'A helpful Gemini-powered assistant.',
@@ -0,0 +1,5 @@
1
+ export type ThemeMode = 'light' | 'dark' | 'system'
2
+
3
+ export function normalizeThemeMode(value: unknown): ThemeMode {
4
+ return value === 'light' || value === 'system' ? value : 'dark'
5
+ }
@@ -1,5 +1,6 @@
1
1
  import type { SessionResetMode } from './session'
2
2
  import type { ExtensionManagedLocalFolderDeclaration } from './extension'
3
+ import type { ThemeMode } from '@/lib/theme-mode'
3
4
 
4
5
  // --- App Settings ---
5
6
  export type LoopMode = 'bounded' | 'ongoing'
@@ -134,6 +135,7 @@ export interface AppSettings {
134
135
  defaultAgentId?: string | null
135
136
  // Theme
136
137
  themeHue?: string
138
+ themeMode?: ThemeMode
137
139
  // Web search provider
138
140
  webSearchProvider?: 'duckduckgo' | 'google' | 'bing' | 'searxng' | 'tavily' | 'brave' | 'exa'
139
141
  searxngUrl?: string
@@ -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' | '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' | 'lmstudio' | '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' | 'tokenmix' | 'ollama' | 'anthropic' | 'openclaw' | 'hermes' | 'lmstudio' | 'google' | 'deepseek' | 'groq' | 'together' | 'mistral' | 'xai' | 'fireworks' | 'nebius' | 'deepinfra'
2
2
  export type ProviderId = ProviderType | (string & {})
3
3
 
4
4
  export interface ProviderInfo {
@@ -1,7 +1,10 @@
1
1
  'use client'
2
2
 
3
3
  import { useState } from 'react'
4
+ import { Monitor, Moon, Sun } from 'lucide-react'
5
+ import { useTheme } from 'next-themes'
4
6
  import { toast } from 'sonner'
7
+ import { normalizeThemeMode, type ThemeMode } from '@/lib/theme-mode'
5
8
  import type { SettingsSectionProps } from './types'
6
9
 
7
10
  const PRESETS = [
@@ -13,12 +16,26 @@ const PRESETS = [
13
16
  { label: 'Rose', color: '#2e1a24' },
14
17
  ]
15
18
 
19
+ const THEME_MODES: Array<{ id: ThemeMode; label: string; Icon: typeof Sun }> = [
20
+ { id: 'light', label: 'Light', Icon: Sun },
21
+ { id: 'dark', label: 'Dark', Icon: Moon },
22
+ { id: 'system', label: 'System', Icon: Monitor },
23
+ ]
24
+
16
25
  export function ThemeSection({ appSettings, patchSettings, inputClass }: SettingsSectionProps) {
26
+ const { setTheme } = useTheme()
17
27
  const currentHue = appSettings.themeHue || PRESETS[0].color
28
+ const currentMode = normalizeThemeMode(appSettings.themeMode)
18
29
  const [customHex, setCustomHex] = useState(
19
30
  PRESETS.some((p) => p.color === currentHue) ? '' : currentHue,
20
31
  )
21
32
 
33
+ const applyMode = (mode: ThemeMode) => {
34
+ setTheme(mode)
35
+ patchSettings({ themeMode: mode })
36
+ toast.success('Theme updated')
37
+ }
38
+
22
39
  const applyHue = (color: string) => {
23
40
  patchSettings({ themeHue: color })
24
41
  document.documentElement.style.setProperty('--neutral-tint', color)
@@ -38,9 +55,32 @@ export function ThemeSection({ appSettings, patchSettings, inputClass }: Setting
38
55
  Theme
39
56
  </h3>
40
57
  <p className="text-[12px] text-text-3 mb-5">
41
- Shift the UI color palette. Pick a preset or enter a custom hex color.
58
+ Choose a color scheme and shift the UI palette with a preset or custom hex color.
42
59
  </p>
43
60
 
61
+ <div className="inline-grid grid-cols-3 rounded-[8px] border border-white/[0.08] bg-white/[0.03] p-1 mb-5">
62
+ {THEME_MODES.map(({ id, label, Icon }) => {
63
+ const isActive = currentMode === id
64
+ return (
65
+ <button
66
+ key={id}
67
+ type="button"
68
+ onClick={() => applyMode(id)}
69
+ aria-pressed={isActive}
70
+ className={`h-9 px-3 rounded-[6px] flex items-center justify-center gap-2 text-[12px] font-600 transition-colors ${
71
+ isActive
72
+ ? 'bg-accent text-white'
73
+ : 'text-text-3 hover:text-text hover:bg-white/[0.05]'
74
+ }`}
75
+ title={label}
76
+ >
77
+ <Icon className="w-4 h-4" aria-hidden="true" />
78
+ <span>{label}</span>
79
+ </button>
80
+ )
81
+ })}
82
+ </div>
83
+
44
84
  {/* Preset swatches */}
45
85
  <div className="flex flex-wrap gap-3 mb-4">
46
86
  {PRESETS.map((preset) => {