Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.jp.md
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ DeepChatはメッセージアプリからリモート操作できるため、デ
<img src="./src/renderer/src/assets/llm-icons/obscurify.svg" width="50" height="50" alt="Obscurify.ai Icon"><br/>
<a href="https://obscurify.ai/?utm_source=deepchat">Obscurify.ai</a>
</td>
<td>
<img src="./src/renderer/src/assets/llm-icons/wally-color.svg" width="50" height="50" alt="Wally Icon"><br/>
<a href="https://www.runwally.com/">Wally</a>
</td>
</tr>

</table>
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,10 @@ Common commands include `/start`, `/help`, `/pair`, `/new`, `/sessions`, `/use`,
<img src="./src/renderer/src/assets/llm-icons/obscurify.svg" width="50" height="50" alt="Obscurify.ai Icon"><br/>
<a href="https://obscurify.ai/?utm_source=deepchat">Obscurify.ai</a>
</td>
<td>
<img src="./src/renderer/src/assets/llm-icons/wally-color.svg" width="50" height="50" alt="Wally Icon"><br/>
<a href="https://www.runwally.com/">Wally</a>
</td>
</tr>

</table>
Expand Down
4 changes: 4 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,10 @@ DeepChat 可以通过聊天软件远程控制,让你离开桌面后也能继
<img src="./src/renderer/src/assets/llm-icons/obscurify.svg" width="50" height="50" alt="Obscurify.ai Icon"><br/>
<a href="https://obscurify.ai/?utm_source=deepchat">Obscurify.ai</a>
</td>
<td>
<img src="./src/renderer/src/assets/llm-icons/wally-color.svg" width="50" height="50" alt="Wally Icon"><br/>
<a href="https://www.runwally.com/">Wally</a>
</td>
</tr>

</table>
Expand Down
14 changes: 14 additions & 0 deletions src/main/provider/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,20 @@ const PROVIDER_DEFAULTS: LLM_PROVIDER_BASE[] = [
models: 'https://cloudgpu.app/api?utm_source=deepchat'
}
},
{
id: 'wally',
name: 'Wally',
apiType: 'openai-completions',
apiKey: '',
baseUrl: 'https://inference.runanywhere.ai/v1',
enable: false,
websites: {
official: 'https://www.runwally.com/',
apiKey: 'https://console.runanywhere.ai/',
docs: 'https://docs.runanywhere.ai/wally-cloud/api',
models: 'https://www.runwally.com/pricing'
}
},
{
id: 'cheapaimodel',
name: 'cheapaimodel',
Expand Down
13 changes: 13 additions & 0 deletions src/main/provider/providerRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,19 @@ const PROVIDER_ID_REGISTRY = new Map<string, AiSdkProviderDefinition>([
checkMaxTokens: 16
})
],
[
'wally',
createDefinition({
...OPENAI_BASE,
checkStrategy: 'generate-text',
credentialStrategy: 'api-key',
embeddingStrategy: 'none',
checkModelId: 'deepseek-v4.1-flash',
checkPrompt: 'Hello',
checkTemperature: 0.2,
checkMaxTokens: 16
})
],
[
'obscurify',
createDefinition({
Expand Down
1 change: 1 addition & 0 deletions src/renderer/src/assets/llm-icons/wally-color.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/renderer/src/components/icons/modelIconRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import opperColorIcon from '@/assets/llm-icons/opper.svg?url'
import aistupidlevelIcon from '@/assets/llm-icons/aistupidlevel.svg?url'
import runcrateIcon from '@/assets/llm-icons/runcrate.svg?url'
import cloudgpuIcon from '@/assets/llm-icons/cloudgpu.svg?url'
import wallyColorIcon from '@/assets/llm-icons/wally-color.svg?url'
import cheapaimodelIcon from '@/assets/llm-icons/cheapaimodel.svg?url'
import obscurifyIcon from '@/assets/llm-icons/obscurify.svg?url'
import demonrouteColorIcon from '@/assets/llm-icons/demonroute.svg?url'
Expand Down Expand Up @@ -210,6 +211,7 @@ export const modelIcons = {
aistupidlevel: aistupidlevelIcon,
runcrate: runcrateIcon,
cloudgpu: cloudgpuIcon,
wally: wallyColorIcon,
cheapaimodel: cheapaimodelIcon,
obscurify: obscurifyIcon,
demonroute: demonrouteColorIcon,
Expand Down
34 changes: 34 additions & 0 deletions test/main/provider/basicApiKeyProviders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,40 @@ describe('basic API-key provider registrations', () => {
)
})

it('checks Wally with a chat model instead of its public model list', async () => {
const defaults = DEFAULT_PROVIDERS.find((provider) => provider.id === 'wally')!
expect(defaults).toBeDefined()
const config = { ...defaults, apiKey: 'test-key' }
// Wally's /v1/models answers without a key, so listing models cannot validate one.
expect(resolveAiSdkProviderDefinition(config)).toMatchObject({
runtimeKind: 'openai-compatible',
modelSource: 'openai',
checkStrategy: 'generate-text',
credentialStrategy: 'api-key',
embeddingStrategy: 'none',
checkModelId: 'deepseek-v4.1-flash'
})
const provider = new AiSdkProvider(config, createProviderSettings())
;(provider as any).isInitialized = true

await expect(provider.check()).resolves.toEqual({ isOk: true, errorMsg: null })
expect(mockRunAiSdkGenerateText).toHaveBeenCalledWith(
expect.objectContaining({
providerKind: 'openai-compatible',
provider: expect.objectContaining({
id: 'wally',
apiKey: 'test-key',
baseUrl: 'https://inference.runanywhere.ai/v1'
})
}),
[{ role: 'user', content: 'Hello' }],
'deepseek-v4.1-flash',
expect.any(Object),
0.2,
16
)
})

it('lists every CloudGPU catalog id except non-chat models', async () => {
const defaults = DEFAULT_PROVIDERS.find(({ id }) => id === 'cloudgpu')!
const fetchMock = vi.fn().mockResolvedValue(
Expand Down
19 changes: 19 additions & 0 deletions test/main/provider/defaultProviders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@ describe('DEFAULT_PROVIDERS', () => {
)
})

it('includes Wally as a disabled built-in OpenAI-compatible provider', () => {
expect(DEFAULT_PROVIDERS).toContainEqual(
expect.objectContaining({
id: 'wally',
name: 'Wally',
apiType: 'openai-completions',
baseUrl: 'https://inference.runanywhere.ai/v1',
enable: false,
websites: expect.objectContaining({
official: 'https://www.runwally.com/',
apiKey: 'https://console.runanywhere.ai/',
docs: 'https://docs.runanywhere.ai/wally-cloud/api',
models: 'https://www.runwally.com/pricing',
defaultBaseUrl: 'https://inference.runanywhere.ai/v1'
})
})
)
})

it('includes Obscurify.ai as a disabled built-in OpenAI-compatible provider', () => {
expect(DEFAULT_PROVIDERS).toContainEqual(
expect.objectContaining({
Expand Down