robot-resources 1.2.6 → 1.2.7

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/lib/detect.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { execSync, execFileSync } from 'node:child_process';
2
- import { existsSync } from 'node:fs';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
 
@@ -88,6 +88,61 @@ export function isOpenClawPluginInstalled() {
88
88
  return existsSync(join(home, '.openclaw', 'extensions', 'robot-resources-router'));
89
89
  }
90
90
 
91
+ /**
92
+ * Detect OpenClaw auth mode: 'subscription' (OAuth token) or 'apikey'.
93
+ *
94
+ * Subscription users authenticate via Anthropic OAuth tokens.
95
+ * Anthropic rejects these tokens from third-party clients, so the
96
+ * only viable routing path is the OpenClaw plugin (not HTTP proxy).
97
+ *
98
+ * Detection order:
99
+ * 1. ANTHROPIC_AUTH_TOKEN env var → subscription
100
+ * 2. openclaw.json → auth.type or providers.anthropic.authToken
101
+ * 3. providers.anthropic.apiKey → apikey
102
+ * 4. Default → apikey (conservative — proxy works fine)
103
+ */
104
+ export function getOpenClawAuthMode() {
105
+ // Env var is the strongest signal
106
+ if (process.env.ANTHROPIC_AUTH_TOKEN) return 'subscription';
107
+ if (process.env.ANTHROPIC_API_KEY) return 'apikey';
108
+
109
+ // Try reading openclaw.json
110
+ const home = homedir();
111
+ const candidates = [
112
+ join(home, '.openclaw', 'openclaw.json'),
113
+ join(home, 'openclaw.json'),
114
+ ];
115
+
116
+ for (const configPath of candidates) {
117
+ if (!existsSync(configPath)) continue;
118
+
119
+ try {
120
+ const raw = readFileSync(configPath, 'utf-8');
121
+ // Strip JSON5 features inline (comments + trailing commas)
122
+ const clean = raw
123
+ .replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\/\/.*$|\/\*[\s\S]*?\*\//gm,
124
+ (m) => (m.startsWith('"') || m.startsWith("'") ? m : ''))
125
+ .replace(/,\s*([\]}])/g, '$1');
126
+ const config = JSON.parse(clean);
127
+
128
+ // Check explicit auth type
129
+ if (config.auth?.type === 'oauth' || config.auth?.type === 'subscription') {
130
+ return 'subscription';
131
+ }
132
+
133
+ // Check for authToken in providers
134
+ const anthropic = config.models?.providers?.anthropic
135
+ || config.providers?.anthropic;
136
+ if (anthropic?.authToken) return 'subscription';
137
+ if (anthropic?.apiKey) return 'apikey';
138
+ } catch {
139
+ // Config unreadable — fall through
140
+ }
141
+ }
142
+
143
+ return 'apikey';
144
+ }
145
+
91
146
  /**
92
147
  * Check if the router service is already registered.
93
148
  */
@@ -1,5 +1,5 @@
1
1
  import { execFileSync } from 'node:child_process';
2
- import { isOpenClawInstalled, isOpenClawPluginInstalled } from './detect.js';
2
+ import { isOpenClawInstalled, isOpenClawPluginInstalled, getOpenClawAuthMode } from './detect.js';
3
3
 
4
4
  /**
5
5
  * Strip JSON5 features (comments + trailing commas) to produce valid JSON.
@@ -25,12 +25,20 @@ function stripJson5(text) {
25
25
  * native plugin system. The plugin uses before_model_resolve to
26
26
  * override the provider — survives gateway restarts because it
27
27
  * lives in ~/.openclaw/extensions/, not in openclaw.json.
28
+ *
29
+ * Auth mode detection:
30
+ * - subscription (OAuth token): Plugin is REQUIRED. Anthropic rejects
31
+ * OAuth tokens from third-party clients, so HTTP proxy won't work.
32
+ * - apikey: Plugin is preferred (survives restarts) but proxy also works.
28
33
  */
29
34
  function configureOpenClaw() {
35
+ const authMode = getOpenClawAuthMode();
36
+
30
37
  if (isOpenClawPluginInstalled()) {
31
38
  return {
32
39
  name: 'OpenClaw',
33
40
  action: 'already_configured',
41
+ authMode,
34
42
  };
35
43
  }
36
44
 
@@ -42,17 +50,33 @@ function configureOpenClaw() {
42
50
  return {
43
51
  name: 'OpenClaw',
44
52
  action: 'installed',
53
+ authMode,
54
+ note: authMode === 'subscription'
55
+ ? 'Plugin required — subscription OAuth tokens are rejected by Anthropic when proxied via third-party clients.'
56
+ : undefined,
45
57
  };
46
58
  } catch {
47
59
  // Plugin install failed — fall back to instructions
60
+ const instructions = [
61
+ 'Could not auto-install plugin. Install manually:',
62
+ ' openclaw plugins install @robot-resources/openclaw-plugin',
63
+ ];
64
+
65
+ if (authMode === 'subscription') {
66
+ instructions.push(
67
+ 'IMPORTANT: Subscription mode detected (OAuth token).',
68
+ 'The plugin is required — HTTP proxy cannot forward OAuth tokens.',
69
+ 'Anthropic rejects OAuth tokens from third-party clients.',
70
+ );
71
+ }
72
+
73
+ instructions.push('Docs: https://github.com/robot-resources/robot-resources');
74
+
48
75
  return {
49
76
  name: 'OpenClaw',
50
77
  action: 'instructions',
51
- instructions: [
52
- 'Could not auto-install plugin. Install manually:',
53
- ' openclaw plugins install @robot-resources/openclaw-plugin',
54
- 'Docs: https://github.com/robot-resources/robot-resources',
55
- ],
78
+ authMode,
79
+ instructions,
56
80
  };
57
81
  }
58
82
  }
package/lib/wizard.js CHANGED
@@ -185,8 +185,11 @@ export async function runWizard({ nonInteractive = false } = {}) {
185
185
  success(`${r.name}: routing through localhost:3838`);
186
186
  } else if (r.action === 'already_configured') {
187
187
  success(`${r.name}: already configured`);
188
+ } else if (r.action === 'installed') {
189
+ success(`${r.name}: plugin installed`);
190
+ if (r.note) info(` ${r.note}`);
188
191
  } else if (r.action === 'instructions') {
189
- info(`${r.name}: manual configuration needed:`);
192
+ warn(`${r.name}: manual configuration needed:`);
190
193
  for (const instruction of r.instructions) {
191
194
  info(` ${instruction}`);
192
195
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "robot-resources",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
4
4
  "description": "Robot Resources — AI agent runtime tools. One command to install everything.",
5
5
  "type": "module",
6
6
  "bin": {