@formthefog/stratus 2026.2.17
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/LICENSE +21 -0
- package/README.md +719 -0
- package/TROUBLESHOOTING.md +245 -0
- package/banner.png +0 -0
- package/index.ts +387 -0
- package/install.sh +215 -0
- package/openclaw.plugin.json +62 -0
- package/package.json +34 -0
- package/skills/stratus-info/SKILL.md +228 -0
- package/src/client.ts +98 -0
- package/src/config.ts +70 -0
- package/src/setup.ts +210 -0
- package/src/types.ts +56 -0
- package/verify.sh +110 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# Troubleshooting Guide
|
|
2
|
+
|
|
3
|
+
## Common Issues and Solutions
|
|
4
|
+
|
|
5
|
+
### Silent Fallback to Anthropic (SIGBART ignores Stratus config)
|
|
6
|
+
|
|
7
|
+
**Symptoms:**
|
|
8
|
+
- SIGBART says "NOW RUNNING: Anthropic (Claude Opus 4.5)"
|
|
9
|
+
- Stratus API key configured in `~/.openclaw/openclaw.json`
|
|
10
|
+
- No obvious errors in logs
|
|
11
|
+
- OpenClaw gateway running normally
|
|
12
|
+
|
|
13
|
+
**Root Cause:**
|
|
14
|
+
OpenClaw maintains **TWO separate locations** for API authentication:
|
|
15
|
+
|
|
16
|
+
1. **Config file** (`~/.openclaw/openclaw.json`) - What you edit
|
|
17
|
+
2. **Auth cache** (`~/.openclaw/agents/main/agent/auth-profiles.json`) - What the gateway actually uses
|
|
18
|
+
|
|
19
|
+
**The config file does NOT automatically sync to the auth cache.**
|
|
20
|
+
|
|
21
|
+
**Solution:**
|
|
22
|
+
|
|
23
|
+
1. Update both files with your Stratus API key:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 1. Update config (you probably already did this)
|
|
27
|
+
vim ~/.openclaw/openclaw.json
|
|
28
|
+
|
|
29
|
+
# 2. Update auth cache (THIS IS CRITICAL)
|
|
30
|
+
vim ~/.openclaw/agents/main/agent/auth-profiles.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
2. In `auth-profiles.json`, add or update the Stratus profile:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"profiles": [
|
|
38
|
+
{
|
|
39
|
+
"provider": "stratus",
|
|
40
|
+
"baseUrl": "https://dev.api.stratus.run/v1",
|
|
41
|
+
"apiKey": "stratus_sk_your_actual_key_here"
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
3. Restart OpenClaw gateway:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
openclaw gateway restart
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
4. Verify auth is working with manual curl:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
curl https://dev.api.stratus.run/v1/chat/completions \
|
|
57
|
+
-H "Content-Type: application/json" \
|
|
58
|
+
-H "Authorization: Bearer stratus_sk_your_actual_key_here" \
|
|
59
|
+
-d '{
|
|
60
|
+
"model": "stratus-x1ac-base-claude-sonnet-4-5",
|
|
61
|
+
"messages": [{"role": "user", "content": "Test"}],
|
|
62
|
+
"max_tokens": 50
|
|
63
|
+
}'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Expected: `200 OK` with a response and credit balance
|
|
67
|
+
|
|
68
|
+
**Key Learning:**
|
|
69
|
+
- Always check **both** config and auth cache files
|
|
70
|
+
- Auth cache doesn't auto-sync from config
|
|
71
|
+
- 401 Unauthorized = auth cache issue, not endpoint issue
|
|
72
|
+
- Use manual curl to verify auth independently
|
|
73
|
+
|
|
74
|
+
**Verification Success (2026-02-15):**
|
|
75
|
+
After fixing the auth cache issue:
|
|
76
|
+
- ✅ API endpoint responding: `dev.api.stratus.run`
|
|
77
|
+
- ✅ Authentication working: API key validated
|
|
78
|
+
- ✅ User balance confirmed: 17784.00 credits
|
|
79
|
+
- ✅ Model available: `stratus-x1ac-base-claude-sonnet-4-5`
|
|
80
|
+
- ❌ **Next blocker**: Role field compatibility (see section below)
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### Role Field Compatibility Issue
|
|
85
|
+
|
|
86
|
+
**Symptoms:**
|
|
87
|
+
- OpenClaw sends `role: "developer"` in messages
|
|
88
|
+
- Stratus API returns error: `"messages: Unexpected role 'developer'. Allowed roles are 'user' or 'assistant'"`
|
|
89
|
+
- May see validation errors about invalid role values
|
|
90
|
+
|
|
91
|
+
**Root Cause:**
|
|
92
|
+
OpenClaw uses Anthropic's `developer` role for system-level instructions, but the Stratus API (which wraps Anthropic's Messages API) expects only `user` or `assistant` roles. The `developer` role is Anthropic-specific but not supported when using the OpenAI-compatible `/v1/chat/completions` endpoint.
|
|
93
|
+
|
|
94
|
+
**Impact:**
|
|
95
|
+
After successfully authenticating and verifying API key/balance, actual chat completion requests fail with role validation errors.
|
|
96
|
+
|
|
97
|
+
**Current Status (2026-02-15):**
|
|
98
|
+
✅ **Authentication working** - API key verified, user balance confirmed (17784.00 credits)
|
|
99
|
+
❌ **Chat completions blocked** - Role field validation prevents actual usage
|
|
100
|
+
🔧 **Fix needed** - Plugin must transform `developer` → `system` for OpenAI-compatible providers
|
|
101
|
+
|
|
102
|
+
**Solution Options:**
|
|
103
|
+
|
|
104
|
+
**Option 1: Patch Stratus Plugin (RECOMMENDED)** ✅
|
|
105
|
+
Add role mapping in the OpenClaw Stratus plugin before sending to API:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// In src/client.ts
|
|
109
|
+
function normalizeRole(role: string): string {
|
|
110
|
+
// Map Anthropic-specific roles to OpenAI-compatible roles
|
|
111
|
+
if (role === 'developer') return 'system';
|
|
112
|
+
return role;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Then in chat completion method:
|
|
116
|
+
const normalizedMessages = messages.map(msg => ({
|
|
117
|
+
...msg,
|
|
118
|
+
role: normalizeRole(msg.role)
|
|
119
|
+
}));
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Option 2: File OpenClaw Bug**
|
|
123
|
+
Request OpenClaw core to handle role mapping for `openai-completions` API format providers automatically.
|
|
124
|
+
|
|
125
|
+
**Option 3: Use Anthropic Messages API**
|
|
126
|
+
Switch from `/v1/chat/completions` (OpenAI format) to `/v1/messages` (native Anthropic format), which natively supports the `developer` role.
|
|
127
|
+
|
|
128
|
+
**Recommended Path:**
|
|
129
|
+
Implement Option 1 (plugin-level role mapping) as it provides maximum compatibility and doesn't depend on upstream changes.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### "Stratus API key not configured"
|
|
134
|
+
|
|
135
|
+
**Cause**: No API key found in config or environment.
|
|
136
|
+
|
|
137
|
+
**Solution**:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
export STRATUS_API_KEY=stratus_sk_live_your_key_here
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Or run the setup wizard:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
/stratus setup
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### "Invalid Stratus API key format"
|
|
152
|
+
|
|
153
|
+
**Cause**: API key doesn't start with `stratus_sk_`.
|
|
154
|
+
|
|
155
|
+
**Solution**: Verify your API key from [stratus.run](https://stratus.run).
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### "Tool not available"
|
|
160
|
+
|
|
161
|
+
**Cause**: Tool not in allowlist.
|
|
162
|
+
|
|
163
|
+
**Solution**:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
openclaw config set agents.defaults.tools.allow '["stratus_embeddings", "stratus_rollout"]'
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### "Stratus API error (401)"
|
|
172
|
+
|
|
173
|
+
**Cause**: Invalid, expired, or cached API key.
|
|
174
|
+
|
|
175
|
+
**Solution**:
|
|
176
|
+
|
|
177
|
+
1. Get a new API key from [stratus.run](https://stratus.run)
|
|
178
|
+
2. Update BOTH config files:
|
|
179
|
+
- `~/.openclaw/openclaw.json`
|
|
180
|
+
- `~/.openclaw/agents/main/agent/auth-profiles.json`
|
|
181
|
+
3. Restart gateway: `openclaw gateway restart`
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### "Stratus API error (429)"
|
|
186
|
+
|
|
187
|
+
**Cause**: Rate limit exceeded.
|
|
188
|
+
|
|
189
|
+
**Solution**: Wait and retry, or upgrade your Stratus plan.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Debugging Checklist
|
|
194
|
+
|
|
195
|
+
When Stratus integration isn't working:
|
|
196
|
+
|
|
197
|
+
1. **Verify API key format**: Should start with `stratus_sk_`
|
|
198
|
+
2. **Check config file**: `cat ~/.openclaw/openclaw.json | grep stratus`
|
|
199
|
+
3. **Check auth cache**: `cat ~/.openclaw/agents/main/agent/auth-profiles.json`
|
|
200
|
+
4. **Test with curl**: Use manual curl command (see above)
|
|
201
|
+
5. **Check gateway logs**: `openclaw gateway logs`
|
|
202
|
+
6. **Restart gateway**: `openclaw gateway restart`
|
|
203
|
+
7. **Verify endpoint**: Should be `https://dev.api.stratus.run/v1`
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Known Issues
|
|
208
|
+
|
|
209
|
+
### Auth Cache Staleness
|
|
210
|
+
|
|
211
|
+
**Issue**: Changes to `openclaw.json` don't automatically sync to `auth-profiles.json`.
|
|
212
|
+
|
|
213
|
+
**Impact**: Gateway continues using old/invalid credentials even after config update.
|
|
214
|
+
|
|
215
|
+
**Workaround**: Manually update both files.
|
|
216
|
+
|
|
217
|
+
**Future Enhancement**: OpenClaw should auto-sync config → auth cache on gateway restart.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
### Role Field Mapping
|
|
222
|
+
|
|
223
|
+
**Issue**: OpenClaw uses `developer` role, OpenAI uses `system` role.
|
|
224
|
+
|
|
225
|
+
**Impact**: May cause validation errors with strict OpenAI-compatible APIs.
|
|
226
|
+
|
|
227
|
+
**Workaround**: Stratus API now accepts `developer` role (deployed 2026-02-14).
|
|
228
|
+
|
|
229
|
+
**Future Enhancement**: Plugin should map roles for maximum compatibility.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Getting Help
|
|
234
|
+
|
|
235
|
+
If none of these solutions work:
|
|
236
|
+
|
|
237
|
+
1. Check gateway logs: `openclaw gateway logs`
|
|
238
|
+
2. File an issue: [GitHub Issues](https://github.com/openclaw/openclaw/issues)
|
|
239
|
+
3. Contact Stratus support: support@stratus.run
|
|
240
|
+
|
|
241
|
+
Include in your report:
|
|
242
|
+
- OpenClaw version: `openclaw --version`
|
|
243
|
+
- Plugin version: `cat ~/.openclaw/plugins/stratus/package.json | grep version`
|
|
244
|
+
- Relevant logs from `openclaw gateway logs`
|
|
245
|
+
- Steps to reproduce
|
package/banner.png
ADDED
|
Binary file
|
package/index.ts
ADDED
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import type { StratusPluginConfig } from "./src/types.js";
|
|
4
|
+
import { createStratusClient } from "./src/client.js";
|
|
5
|
+
import { StratusConfigSchema } from "./src/config.js";
|
|
6
|
+
import { setupStratus } from "./src/setup.js";
|
|
7
|
+
|
|
8
|
+
const PROVIDER_ID = "stratus";
|
|
9
|
+
const PROVIDER_LABEL = "Stratus";
|
|
10
|
+
const DEFAULT_BASE_URL = "https://dev.api.stratus.run/v1";
|
|
11
|
+
|
|
12
|
+
function buildModelDefinition(params: {
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
contextWindow?: number;
|
|
16
|
+
maxTokens?: number;
|
|
17
|
+
}) {
|
|
18
|
+
return {
|
|
19
|
+
id: params.id,
|
|
20
|
+
name: params.name,
|
|
21
|
+
reasoning: true,
|
|
22
|
+
input: ["text", "image"] as const,
|
|
23
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
24
|
+
contextWindow: params.contextWindow || 128000,
|
|
25
|
+
maxTokens: params.maxTokens || 8192,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const STRATUS_SIZES = ["small", "base", "large", "xl", "huge"] as const;
|
|
30
|
+
|
|
31
|
+
const OPENAI_MODELS = [
|
|
32
|
+
{ id: "gpt-4o", name: "GPT-4o", context: 128000, tokens: 8192 },
|
|
33
|
+
{ id: "gpt-4o-mini", name: "GPT-4o Mini", context: 128000, tokens: 8192 },
|
|
34
|
+
{ id: "gpt-4-turbo", name: "GPT-4 Turbo", context: 128000, tokens: 4096 },
|
|
35
|
+
{ id: "gpt-4", name: "GPT-4", context: 8192, tokens: 4096 },
|
|
36
|
+
{ id: "gpt-3.5-turbo", name: "GPT-3.5 Turbo", context: 16385, tokens: 4096 },
|
|
37
|
+
] as const;
|
|
38
|
+
|
|
39
|
+
const ANTHROPIC_MODELS = [
|
|
40
|
+
{ id: "claude-sonnet-4-5", name: "Claude 4.5 Sonnet", context: 200000, tokens: 8192 },
|
|
41
|
+
{ id: "claude-opus-4-5", name: "Claude 4.5 Opus", context: 200000, tokens: 8192 },
|
|
42
|
+
{ id: "claude-sonnet-4", name: "Claude 4 Sonnet", context: 200000, tokens: 8192 },
|
|
43
|
+
{ id: "claude-opus-4", name: "Claude 4 Opus", context: 200000, tokens: 8192 },
|
|
44
|
+
{ id: "claude-haiku-4-5", name: "Claude 4.5 Haiku", context: 200000, tokens: 8192 },
|
|
45
|
+
{ id: "claude-3-7-sonnet", name: "Claude 3.7 Sonnet", context: 200000, tokens: 8192 },
|
|
46
|
+
{ id: "claude-3-5-sonnet", name: "Claude 3.5 Sonnet", context: 200000, tokens: 8192 },
|
|
47
|
+
{ id: "claude-3-opus", name: "Claude 3 Opus", context: 200000, tokens: 4096 },
|
|
48
|
+
{ id: "claude-3-sonnet", name: "Claude 3 Sonnet", context: 200000, tokens: 4096 },
|
|
49
|
+
{ id: "claude-3-haiku", name: "Claude 3 Haiku", context: 200000, tokens: 4096 },
|
|
50
|
+
] as const;
|
|
51
|
+
|
|
52
|
+
function generateAllModels() {
|
|
53
|
+
const models = [];
|
|
54
|
+
|
|
55
|
+
for (const size of STRATUS_SIZES) {
|
|
56
|
+
const sizeLabel = size.charAt(0).toUpperCase() + size.slice(1);
|
|
57
|
+
|
|
58
|
+
for (const llm of OPENAI_MODELS) {
|
|
59
|
+
models.push(
|
|
60
|
+
buildModelDefinition({
|
|
61
|
+
id: `stratus-x1ac-${size}-${llm.id}`,
|
|
62
|
+
name: `Stratus X1AC ${sizeLabel} (${llm.name})`,
|
|
63
|
+
contextWindow: llm.context,
|
|
64
|
+
maxTokens: llm.tokens,
|
|
65
|
+
}),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const llm of ANTHROPIC_MODELS) {
|
|
70
|
+
models.push(
|
|
71
|
+
buildModelDefinition({
|
|
72
|
+
id: `stratus-x1ac-${size}-${llm.id}`,
|
|
73
|
+
name: `Stratus X1AC ${sizeLabel} (${llm.name})`,
|
|
74
|
+
contextWindow: llm.context,
|
|
75
|
+
maxTokens: llm.tokens,
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return models;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const stratusPlugin = {
|
|
85
|
+
id: "stratus",
|
|
86
|
+
name: "Stratus API Integration",
|
|
87
|
+
description: "Stratus V3 (X1-AC) action-conditioned JEPA for autonomous agent planning",
|
|
88
|
+
configSchema: StratusConfigSchema,
|
|
89
|
+
|
|
90
|
+
register(api: OpenClawPluginApi) {
|
|
91
|
+
const pluginConfig = StratusConfigSchema.parse(api.pluginConfig) as StratusPluginConfig;
|
|
92
|
+
|
|
93
|
+
api.registerProvider({
|
|
94
|
+
id: PROVIDER_ID,
|
|
95
|
+
label: PROVIDER_LABEL,
|
|
96
|
+
docsPath: "/providers/stratus",
|
|
97
|
+
aliases: ["stratus-run"],
|
|
98
|
+
auth: [
|
|
99
|
+
{
|
|
100
|
+
id: "api-key",
|
|
101
|
+
label: "API Key",
|
|
102
|
+
kind: "api_key",
|
|
103
|
+
run: async (ctx) => {
|
|
104
|
+
const apiKey = await ctx.prompter.text({
|
|
105
|
+
message: "Enter your Stratus API key:",
|
|
106
|
+
validate: (val: string) => {
|
|
107
|
+
if (!val.trim()) {
|
|
108
|
+
return "API key is required";
|
|
109
|
+
}
|
|
110
|
+
if (!val.startsWith("stratus_sk_")) {
|
|
111
|
+
return "API key must start with 'stratus_sk_'";
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const profileId = `${PROVIDER_ID}:default`;
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
profiles: [
|
|
121
|
+
{
|
|
122
|
+
profileId,
|
|
123
|
+
credential: {
|
|
124
|
+
type: "api_key",
|
|
125
|
+
provider: PROVIDER_ID,
|
|
126
|
+
key: apiKey,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
configPatch: {
|
|
131
|
+
models: {
|
|
132
|
+
providers: {
|
|
133
|
+
[PROVIDER_ID]: {
|
|
134
|
+
baseUrl: DEFAULT_BASE_URL,
|
|
135
|
+
apiKey: apiKey,
|
|
136
|
+
api: "openai-completions",
|
|
137
|
+
models: generateAllModels(),
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
agents: {
|
|
142
|
+
defaults: {
|
|
143
|
+
models: {
|
|
144
|
+
[`${PROVIDER_ID}/stratus-x1ac-base-claude-sonnet-4-5`]: {
|
|
145
|
+
alias: "stratus",
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
defaultModel: `${PROVIDER_ID}/stratus-x1ac-base-claude-sonnet-4-5`,
|
|
152
|
+
notes: [
|
|
153
|
+
"🌊 Stratus X1-AC: World Model + Collective Intelligence System",
|
|
154
|
+
"",
|
|
155
|
+
"NOT just an LLM wrapper — this is predictive planning:",
|
|
156
|
+
" Traditional agents: see → think → act → see again",
|
|
157
|
+
" Stratus agents: see → simulate outcomes → pick best → act",
|
|
158
|
+
"",
|
|
159
|
+
"Architecture:",
|
|
160
|
+
" • World Model (X1): Predicts future states from actions (JEPA-based)",
|
|
161
|
+
" • Policy Head (X1-AC): Selects optimal actions toward goals",
|
|
162
|
+
" • Collective Network: Agents learn from each other in real-time",
|
|
163
|
+
"",
|
|
164
|
+
"Available Tools:",
|
|
165
|
+
" • stratus_embeddings() - 768-dim semantic state embeddings",
|
|
166
|
+
" • stratus_rollout() - Multi-step action sequence planning",
|
|
167
|
+
"",
|
|
168
|
+
"Learn more: /stratus-info (bundled skill)",
|
|
169
|
+
"Technical docs: https://stratus.run/docs/technical-overview",
|
|
170
|
+
],
|
|
171
|
+
};
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (!pluginConfig.tools?.embeddings?.enabled && !pluginConfig.tools?.rollout?.enabled) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (pluginConfig.tools?.embeddings?.enabled) {
|
|
182
|
+
api.registerTool(
|
|
183
|
+
{
|
|
184
|
+
name: "stratus_embeddings",
|
|
185
|
+
label: "Stratus Embeddings",
|
|
186
|
+
description:
|
|
187
|
+
"Generate 768-dimensional state embeddings for semantic search and memory. Use this for understanding semantic relationships between states or actions.",
|
|
188
|
+
parameters: Type.Object({
|
|
189
|
+
input: Type.Union(
|
|
190
|
+
[
|
|
191
|
+
Type.String({ description: "Single text to embed" }),
|
|
192
|
+
Type.Array(Type.String(), { description: "Multiple texts to embed" }),
|
|
193
|
+
],
|
|
194
|
+
{ description: "Text or array of texts to generate embeddings for" },
|
|
195
|
+
),
|
|
196
|
+
model: Type.Optional(
|
|
197
|
+
Type.String({
|
|
198
|
+
description: "Stratus model to use",
|
|
199
|
+
default: "stratus-x1ac-base",
|
|
200
|
+
}),
|
|
201
|
+
),
|
|
202
|
+
encoding_format: Type.Optional(
|
|
203
|
+
Type.Union([Type.Literal("float"), Type.Literal("base64")], {
|
|
204
|
+
default: "float",
|
|
205
|
+
description: "Format for embedding vectors",
|
|
206
|
+
}),
|
|
207
|
+
),
|
|
208
|
+
}),
|
|
209
|
+
async execute(_toolCallId, params, context) {
|
|
210
|
+
const client = createStratusClient(pluginConfig);
|
|
211
|
+
|
|
212
|
+
const response = await client.embeddings({
|
|
213
|
+
input: params.input,
|
|
214
|
+
model: params.model,
|
|
215
|
+
encoding_format: params.encoding_format,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const count = response.data.length;
|
|
219
|
+
const dimensions = Array.isArray(response.data[0]?.embedding)
|
|
220
|
+
? response.data[0].embedding.length
|
|
221
|
+
: 768;
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
content: [
|
|
225
|
+
{
|
|
226
|
+
type: "text",
|
|
227
|
+
text: `Generated ${count} embedding${count === 1 ? "" : "s"} (${dimensions} dimensions each)\nModel: ${response.model}\nUsage: ${response.usage.prompt_tokens} tokens`,
|
|
228
|
+
},
|
|
229
|
+
],
|
|
230
|
+
details: response,
|
|
231
|
+
};
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
{ optional: true },
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (pluginConfig.tools?.rollout?.enabled) {
|
|
239
|
+
api.registerTool(
|
|
240
|
+
{
|
|
241
|
+
name: "stratus_rollout",
|
|
242
|
+
label: "Stratus Rollout",
|
|
243
|
+
description:
|
|
244
|
+
"Multi-step rollout prediction for task planning. Predicts action sequences to reach a goal state. Use this for complex task decomposition and planning.",
|
|
245
|
+
parameters: Type.Object({
|
|
246
|
+
goal: Type.String({
|
|
247
|
+
description: "Target state or goal to achieve (e.g., 'book a hotel room')",
|
|
248
|
+
}),
|
|
249
|
+
initial_state: Type.Optional(
|
|
250
|
+
Type.String({
|
|
251
|
+
description: "Starting state (optional, can be inferred from context)",
|
|
252
|
+
}),
|
|
253
|
+
),
|
|
254
|
+
max_steps: Type.Optional(
|
|
255
|
+
Type.Number({
|
|
256
|
+
description: "Maximum rollout steps",
|
|
257
|
+
default: 10,
|
|
258
|
+
minimum: 1,
|
|
259
|
+
maximum: 50,
|
|
260
|
+
}),
|
|
261
|
+
),
|
|
262
|
+
return_intermediate: Type.Optional(
|
|
263
|
+
Type.Boolean({
|
|
264
|
+
description: "Return intermediate states",
|
|
265
|
+
default: true,
|
|
266
|
+
}),
|
|
267
|
+
),
|
|
268
|
+
}),
|
|
269
|
+
async execute(_toolCallId, params, context) {
|
|
270
|
+
const client = createStratusClient(pluginConfig);
|
|
271
|
+
|
|
272
|
+
const response = await client.rollout({
|
|
273
|
+
goal: params.goal,
|
|
274
|
+
initial_state: params.initial_state,
|
|
275
|
+
max_steps: params.max_steps,
|
|
276
|
+
return_intermediate: params.return_intermediate,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const steps = response.steps || [];
|
|
280
|
+
const stepText = steps
|
|
281
|
+
.map((s, i) => `${i + 1}. ${s.action || s.description || "Unknown step"}`)
|
|
282
|
+
.join("\n");
|
|
283
|
+
|
|
284
|
+
const summary = response.success
|
|
285
|
+
? `Successfully planned ${steps.length} steps to reach goal`
|
|
286
|
+
: `Planning incomplete (${steps.length} steps generated)`;
|
|
287
|
+
|
|
288
|
+
return {
|
|
289
|
+
content: [
|
|
290
|
+
{
|
|
291
|
+
type: "text",
|
|
292
|
+
text: `${summary}\nGoal: ${response.goal}\n\nSteps:\n${stepText}`,
|
|
293
|
+
},
|
|
294
|
+
],
|
|
295
|
+
details: response,
|
|
296
|
+
};
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
{ optional: true },
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Register CLI commands
|
|
304
|
+
if (typeof api.registerCommand === "function") {
|
|
305
|
+
api.registerCommand({
|
|
306
|
+
name: "stratus",
|
|
307
|
+
description: "Stratus plugin commands (setup, verify)",
|
|
308
|
+
acceptsArgs: true,
|
|
309
|
+
handler: async (ctx: any) => {
|
|
310
|
+
const args = ctx.args?.trim() ?? "";
|
|
311
|
+
const tokens = args.split(/\s+/).filter(Boolean);
|
|
312
|
+
const subcommand = (tokens[0] || "help").toLowerCase();
|
|
313
|
+
|
|
314
|
+
if (subcommand === "setup") {
|
|
315
|
+
// Run setup
|
|
316
|
+
const result = await setupStratus(ctx.prompter);
|
|
317
|
+
|
|
318
|
+
if (result.success) {
|
|
319
|
+
console.log(`\n✅ ${result.message}\n`);
|
|
320
|
+
if (result.details) {
|
|
321
|
+
result.details.forEach((line) => console.log(line));
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
console.error(`\n❌ ${result.message}\n`);
|
|
325
|
+
if (result.details) {
|
|
326
|
+
result.details.forEach((line) => console.error(line));
|
|
327
|
+
}
|
|
328
|
+
process.exit(1);
|
|
329
|
+
}
|
|
330
|
+
return { text: "" }; // Return empty to avoid double output
|
|
331
|
+
} else if (subcommand === "verify") {
|
|
332
|
+
// Run verify
|
|
333
|
+
console.log("🔍 Verifying Stratus configuration...\n");
|
|
334
|
+
|
|
335
|
+
let errors = 0;
|
|
336
|
+
|
|
337
|
+
// Check 1: Environment variable
|
|
338
|
+
console.log("1️⃣ Checking STRATUS_API_KEY...");
|
|
339
|
+
if (process.env.STRATUS_API_KEY) {
|
|
340
|
+
console.log(" ✓ STRATUS_API_KEY is set");
|
|
341
|
+
} else {
|
|
342
|
+
console.log(" ❌ STRATUS_API_KEY not found");
|
|
343
|
+
errors++;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Check 2: Config exists
|
|
347
|
+
console.log("\n2️⃣ Checking plugin configuration...");
|
|
348
|
+
if (pluginConfig.apiKey || process.env.STRATUS_API_KEY) {
|
|
349
|
+
console.log(" ✓ API key configured");
|
|
350
|
+
} else {
|
|
351
|
+
console.log(" ❌ API key not configured");
|
|
352
|
+
errors++;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
console.log("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
356
|
+
if (errors === 0) {
|
|
357
|
+
console.log("✅ All checks passed!");
|
|
358
|
+
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
|
359
|
+
console.log("🎯 Try it out:");
|
|
360
|
+
console.log(" openclaw agent 'Hello Stratus!' --model stratus\n");
|
|
361
|
+
} else {
|
|
362
|
+
console.log(`❌ ${errors} issue(s) found`);
|
|
363
|
+
console.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
|
364
|
+
console.log("💡 Run: openclaw stratus setup\n");
|
|
365
|
+
process.exit(1);
|
|
366
|
+
}
|
|
367
|
+
return { text: "" }; // Return empty to avoid double output
|
|
368
|
+
} else {
|
|
369
|
+
// Show help
|
|
370
|
+
return {
|
|
371
|
+
text:
|
|
372
|
+
"🌊 Stratus X1-AC Plugin\n\n" +
|
|
373
|
+
"Commands:\n" +
|
|
374
|
+
" /stratus setup - Interactive setup wizard\n" +
|
|
375
|
+
" /stratus verify - Verify configuration\n\n" +
|
|
376
|
+
"Get your API key: https://stratus.run\n" +
|
|
377
|
+
"Docs: https://stratus.run/docs\n" +
|
|
378
|
+
"Issues: https://github.com/formthefog/openclaw-stratus-x1-plugin/issues",
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
export default stratusPlugin;
|