@link-assistant/agent 0.24.2 → 0.24.3
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 +6 -1
- package/package.json +1 -1
- package/src/provider/provider.ts +99 -0
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ This is an MVP implementation of an OpenCode-compatible CLI agent, focused on ma
|
|
|
24
24
|
|
|
25
25
|
- ✅ **JSON Input/Output**: Compatible with `opencode run --format json --model opencode/minimax-m2.5-free`
|
|
26
26
|
- ✅ **Plain Text Input**: Also accepts plain text messages (auto-converted to JSON format)
|
|
27
|
-
- ✅ **Flexible Model Selection**: Defaults to free OpenCode Zen MiniMax M2.5 Free, supports [OpenCode Zen](https://opencode.ai/docs/zen/), [Claude OAuth](../docs/claude-oauth.md), [Groq](../docs/groq.md), and [OpenRouter](../docs/openrouter.md) providers
|
|
27
|
+
- ✅ **Flexible Model Selection**: Defaults to free OpenCode Zen MiniMax M2.5 Free, supports [OpenCode Zen](https://opencode.ai/docs/zen/), [Formal AI](../docs/formal-ai.md), [Claude OAuth](../docs/claude-oauth.md), [Groq](../docs/groq.md), and [OpenRouter](../docs/openrouter.md) providers
|
|
28
28
|
- ✅ **No Restrictions**: Fully unrestricted file system and command execution access (no sandbox)
|
|
29
29
|
- ✅ **Minimal Footprint**: Built with Bun.sh for maximum efficiency
|
|
30
30
|
- ✅ **Full Tool Support**: 13 tools including websearch, codesearch, batch - all enabled by default
|
|
@@ -201,6 +201,10 @@ echo "hi" | agent --model opencode/nemotron-3-super-free
|
|
|
201
201
|
echo "hi" | agent --model opencode/gpt-5-nano
|
|
202
202
|
echo "hi" | agent --model opencode/big-pickle
|
|
203
203
|
|
|
204
|
+
# Formal AI local server
|
|
205
|
+
echo "hi" | agent --model formal-ai
|
|
206
|
+
echo "hi" | agent --model @link-assistant/formal-ai
|
|
207
|
+
|
|
204
208
|
# Premium models (OpenCode Zen subscription)
|
|
205
209
|
echo "hi" | agent --model opencode/sonnet # Claude Sonnet 4.5
|
|
206
210
|
echo "hi" | agent --model opencode/haiku # Claude Haiku 4.5
|
|
@@ -237,6 +241,7 @@ echo "hi" | agent --model github-copilot/gpt-4o # Uses Copilot
|
|
|
237
241
|
```
|
|
238
242
|
|
|
239
243
|
See [MODELS.md](../MODELS.md) for complete list of available models and pricing.
|
|
244
|
+
See [docs/formal-ai.md](../docs/formal-ai.md) for Formal AI local server setup.
|
|
240
245
|
See [docs/groq.md](../docs/groq.md) for Groq provider documentation.
|
|
241
246
|
See [docs/openrouter.md](../docs/openrouter.md) for OpenRouter provider documentation.
|
|
242
247
|
See [docs/claude-oauth.md](../docs/claude-oauth.md) for Claude OAuth provider documentation.
|
package/package.json
CHANGED
package/src/provider/provider.ts
CHANGED
|
@@ -75,7 +75,79 @@ export namespace Provider {
|
|
|
75
75
|
|
|
76
76
|
type Source = 'env' | 'config' | 'custom' | 'api';
|
|
77
77
|
|
|
78
|
+
const FORMAL_AI_DEFAULT_BASE_URL = 'http://127.0.0.1:8080/api/openai/v1';
|
|
79
|
+
const FORMAL_AI_API_KEY_ENV = 'FORMAL_AI_API_KEY';
|
|
80
|
+
const FORMAL_AI_BASE_URL_ENV = 'FORMAL_AI_BASE_URL';
|
|
81
|
+
const FORMAL_AI_DEFAULT_API_KEY = 'formal-ai';
|
|
82
|
+
|
|
83
|
+
function getFormalAiBaseURL(provider?: ModelsDev.Provider) {
|
|
84
|
+
return (
|
|
85
|
+
process.env[FORMAL_AI_BASE_URL_ENV] ??
|
|
86
|
+
provider?.api ??
|
|
87
|
+
FORMAL_AI_DEFAULT_BASE_URL
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function createFormalAiLoader(input?: ModelsDev.Provider) {
|
|
92
|
+
return {
|
|
93
|
+
autoload: true,
|
|
94
|
+
options: {
|
|
95
|
+
apiKey: process.env[FORMAL_AI_API_KEY_ENV] ?? FORMAL_AI_DEFAULT_API_KEY,
|
|
96
|
+
baseURL: getFormalAiBaseURL(input),
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function createFormalAiModel(name = 'Formal AI'): ModelsDev.Model {
|
|
102
|
+
return {
|
|
103
|
+
id: 'formal-ai',
|
|
104
|
+
name,
|
|
105
|
+
release_date: '2026-07-03',
|
|
106
|
+
attachment: false,
|
|
107
|
+
reasoning: true,
|
|
108
|
+
temperature: true,
|
|
109
|
+
tool_call: true,
|
|
110
|
+
cost: {
|
|
111
|
+
input: 0,
|
|
112
|
+
output: 0,
|
|
113
|
+
cache_read: 0,
|
|
114
|
+
cache_write: 0,
|
|
115
|
+
},
|
|
116
|
+
limit: {
|
|
117
|
+
context: 60000,
|
|
118
|
+
output: 8192,
|
|
119
|
+
},
|
|
120
|
+
modalities: {
|
|
121
|
+
input: ['text'],
|
|
122
|
+
output: ['text'],
|
|
123
|
+
},
|
|
124
|
+
options: {},
|
|
125
|
+
provider: {
|
|
126
|
+
npm: '@ai-sdk/openai-compatible',
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function createFormalAiProvider(
|
|
132
|
+
id: string,
|
|
133
|
+
name: string
|
|
134
|
+
): ModelsDev.Provider {
|
|
135
|
+
return {
|
|
136
|
+
id,
|
|
137
|
+
name,
|
|
138
|
+
npm: '@ai-sdk/openai-compatible',
|
|
139
|
+
api: getFormalAiBaseURL(),
|
|
140
|
+
env: [FORMAL_AI_API_KEY_ENV],
|
|
141
|
+
models: {
|
|
142
|
+
'formal-ai': createFormalAiModel('formal-ai'),
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
78
147
|
const CUSTOM_LOADERS: Record<string, CustomLoader> = {
|
|
148
|
+
'formal-ai': async (input) => createFormalAiLoader(input),
|
|
149
|
+
formalai: async (input) => createFormalAiLoader(input),
|
|
150
|
+
'@link-assistant': async (input) => createFormalAiLoader(input),
|
|
79
151
|
async anthropic(input) {
|
|
80
152
|
// Check if OAuth credentials are available via the auth plugin
|
|
81
153
|
const auth = await Auth.get('anthropic');
|
|
@@ -791,6 +863,22 @@ export namespace Provider {
|
|
|
791
863
|
realIdByKey.set('google/gemini-3-pro', 'gemini-3-pro-preview');
|
|
792
864
|
}
|
|
793
865
|
|
|
866
|
+
// Add Formal AI local OpenAI-compatible provider and selectors.
|
|
867
|
+
// Formal AI serves the canonical model ID "formal-ai"; Agent also accepts
|
|
868
|
+
// the scoped selector "@link-assistant/formal-ai" as a provider alias.
|
|
869
|
+
database['formal-ai'] = createFormalAiProvider(
|
|
870
|
+
'formal-ai',
|
|
871
|
+
'Formal AI Local Server'
|
|
872
|
+
);
|
|
873
|
+
database['formalai'] = createFormalAiProvider(
|
|
874
|
+
'formalai',
|
|
875
|
+
'Formal AI Local Server'
|
|
876
|
+
);
|
|
877
|
+
database['@link-assistant'] = createFormalAiProvider(
|
|
878
|
+
'@link-assistant',
|
|
879
|
+
'Formal AI Local Server (@link-assistant alias)'
|
|
880
|
+
);
|
|
881
|
+
|
|
794
882
|
// Add link-assistant echo provider for dry-run testing
|
|
795
883
|
// This synthetic provider echoes back user input without API calls
|
|
796
884
|
// @see https://github.com/link-assistant/agent/issues/89
|
|
@@ -1994,6 +2082,17 @@ export namespace Provider {
|
|
|
1994
2082
|
}
|
|
1995
2083
|
}
|
|
1996
2084
|
|
|
2085
|
+
if (modelID === 'formal-ai') {
|
|
2086
|
+
const formalAiProvider = s.providers['formal-ai'];
|
|
2087
|
+
if (formalAiProvider && formalAiProvider.info.models[modelID]) {
|
|
2088
|
+
log.info(() => ({
|
|
2089
|
+
message: 'resolved short model name to formal-ai (canonical)',
|
|
2090
|
+
modelID,
|
|
2091
|
+
}));
|
|
2092
|
+
return { providerID: 'formal-ai', modelID };
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
|
|
1997
2096
|
// Check if model exists in any provider
|
|
1998
2097
|
const matchingProviders: string[] = [];
|
|
1999
2098
|
for (const [providerID, provider] of Object.entries(s.providers)) {
|