opencode-1password-auth 1.0.1 → 1.0.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/index.ts +48 -23
- package/package.json +1 -1
- package/setup.ps1 +196 -3
- package/setup.sh +205 -3
package/index.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
2
|
import * as sdk from "@1password/sdk";
|
|
3
|
-
import * as fs from "fs";
|
|
4
|
-
import * as path from "path";
|
|
5
|
-
import * as os from "os";
|
|
6
3
|
|
|
7
4
|
interface MCPServerConfig {
|
|
8
5
|
environment?: Record<string, string>;
|
|
@@ -21,13 +18,24 @@ interface AuthJson {
|
|
|
21
18
|
[providerId: string]: ProviderAuth;
|
|
22
19
|
}
|
|
23
20
|
|
|
24
|
-
const
|
|
25
|
-
const OPENCODE_JSON_PATH = path.join(os.homedir(), ".config", "opencode", "opencode.json");
|
|
26
|
-
|
|
27
|
-
export const OnePasswordAuthPlugin: Plugin = async (ctx) => {
|
|
21
|
+
export const OnePasswordAuthPlugin: Plugin = async ({ client, $ }) => {
|
|
28
22
|
let opClient: Awaited<ReturnType<typeof sdk.createClient>> | null = null;
|
|
29
23
|
let mcpsEnvId: string | undefined;
|
|
30
24
|
|
|
25
|
+
const getHomeDir = (): string => {
|
|
26
|
+
return process.env.HOME || process.env.USERPROFILE || "";
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const getAuthJsonPath = (): string => {
|
|
30
|
+
const home = getHomeDir();
|
|
31
|
+
return `${home}/.local/share/opencode/auth.json`;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const getOpenCodeJsonPath = (): string => {
|
|
35
|
+
const home = getHomeDir();
|
|
36
|
+
return `${home}/.config/opencode/opencode.json`;
|
|
37
|
+
};
|
|
38
|
+
|
|
31
39
|
const initClient = async () => {
|
|
32
40
|
const token = process.env.OP_SERVICE_ACCOUNT_TOKEN;
|
|
33
41
|
if (!token) {
|
|
@@ -71,14 +79,21 @@ export const OnePasswordAuthPlugin: Plugin = async (ctx) => {
|
|
|
71
79
|
};
|
|
72
80
|
|
|
73
81
|
const updateAuthJson = async (providerEnvId: string): Promise<void> => {
|
|
74
|
-
|
|
75
|
-
console.log("1Password: auth.json not found, skipping");
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
82
|
+
const authJsonPath = getAuthJsonPath();
|
|
78
83
|
|
|
79
84
|
try {
|
|
80
|
-
|
|
81
|
-
const
|
|
85
|
+
// Read current auth.json using cat
|
|
86
|
+
const catResult = await $`cat "${authJsonPath}"`;
|
|
87
|
+
const content = catResult.stdout;
|
|
88
|
+
let auth: AuthJson;
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
auth = JSON.parse(content);
|
|
92
|
+
} catch {
|
|
93
|
+
console.log("1Password: auth.json is not valid JSON, skipping");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
82
97
|
let modified = false;
|
|
83
98
|
|
|
84
99
|
for (const [providerId, authConfig] of Object.entries(auth)) {
|
|
@@ -91,7 +106,10 @@ export const OnePasswordAuthPlugin: Plugin = async (ctx) => {
|
|
|
91
106
|
}
|
|
92
107
|
|
|
93
108
|
if (modified) {
|
|
94
|
-
|
|
109
|
+
// Write updated content using a temp file and mv
|
|
110
|
+
const newContent = JSON.stringify(auth, null, 2);
|
|
111
|
+
// Use node to write the file since $ heredocs can be tricky
|
|
112
|
+
await $`node -e "const fs=require('fs'); fs.writeFileSync('${authJsonPath}', JSON.stringify(${JSON.stringify(auth)}, null, 2));"`;
|
|
95
113
|
console.log("1Password: auth.json updated to use environment variables");
|
|
96
114
|
}
|
|
97
115
|
} catch (err) {
|
|
@@ -100,14 +118,20 @@ export const OnePasswordAuthPlugin: Plugin = async (ctx) => {
|
|
|
100
118
|
};
|
|
101
119
|
|
|
102
120
|
const updateOpenCodeJsonMCP = async (mcpEnvId: string): Promise<void> => {
|
|
103
|
-
|
|
104
|
-
console.log("1Password: opencode.json not found, skipping");
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
121
|
+
const openCodeJsonPath = getOpenCodeJsonPath();
|
|
107
122
|
|
|
108
123
|
try {
|
|
109
|
-
|
|
110
|
-
const
|
|
124
|
+
// Read current opencode.json using cat
|
|
125
|
+
const catResult = await $`cat "${openCodeJsonPath}"`;
|
|
126
|
+
const content = catResult.stdout;
|
|
127
|
+
let config: OpenCodeConfig;
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
config = JSON.parse(content);
|
|
131
|
+
} catch {
|
|
132
|
+
console.log("1Password: opencode.json is not valid JSON, skipping");
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
111
135
|
|
|
112
136
|
if (!config.mcp) {
|
|
113
137
|
console.log("1Password: No MCP configuration found, skipping");
|
|
@@ -130,7 +154,8 @@ export const OnePasswordAuthPlugin: Plugin = async (ctx) => {
|
|
|
130
154
|
}
|
|
131
155
|
|
|
132
156
|
if (modified) {
|
|
133
|
-
|
|
157
|
+
// Write updated content
|
|
158
|
+
await $`node -e "const fs=require('fs'); fs.writeFileSync('${openCodeJsonPath}', JSON.stringify(${JSON.stringify(config)}, null, 2));"`;
|
|
134
159
|
console.log("1Password: opencode.json MCP config updated to use environment variables");
|
|
135
160
|
}
|
|
136
161
|
} catch (err) {
|
|
@@ -147,7 +172,7 @@ export const OnePasswordAuthPlugin: Plugin = async (ctx) => {
|
|
|
147
172
|
if (!apiKey) continue;
|
|
148
173
|
|
|
149
174
|
try {
|
|
150
|
-
await
|
|
175
|
+
await client.auth.set({
|
|
151
176
|
path: { id: providerId },
|
|
152
177
|
body: { type: "api", key: apiKey },
|
|
153
178
|
});
|
|
@@ -162,7 +187,7 @@ export const OnePasswordAuthPlugin: Plugin = async (ctx) => {
|
|
|
162
187
|
const vars = new Set<string>();
|
|
163
188
|
|
|
164
189
|
try {
|
|
165
|
-
const config =
|
|
190
|
+
const config = client.config as OpenCodeConfig;
|
|
166
191
|
if (config?.mcp) {
|
|
167
192
|
for (const [, serverConfig] of Object.entries(config.mcp)) {
|
|
168
193
|
if (serverConfig?.environment) {
|
package/package.json
CHANGED
package/setup.ps1
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
param(
|
|
5
5
|
[switch]$Uninstall,
|
|
6
|
-
[switch]$Audit
|
|
6
|
+
[switch]$Audit,
|
|
7
|
+
[switch]$UpdateConfig
|
|
7
8
|
)
|
|
8
9
|
|
|
9
10
|
# Colors for output
|
|
@@ -65,6 +66,137 @@ function Remove-RegistryValue {
|
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
|
|
69
|
+
function Get-OpenCodeAuthJsonPath {
|
|
70
|
+
$home = if ($env:USERPROFILE) { $env:USERPROFILE } else { $env:USERPROFILE }
|
|
71
|
+
return "$home/.local/share/opencode/auth.json"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function Get-OpenCodeConfigJsonPath {
|
|
75
|
+
$home = if ($env:USERPROFILE) { $env:USERPROFILE } else { $env:USERPROFILE }
|
|
76
|
+
return "$home/.config/opencode/opencode.json"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function Update-ConfigFiles {
|
|
80
|
+
param([string]$Token, [string]$ProvidersEnvId, [string]$McpsEnvId)
|
|
81
|
+
|
|
82
|
+
$nodeModulesPath = Get-OpenCodeNodeModulesPath
|
|
83
|
+
if (-not $nodeModulesPath) {
|
|
84
|
+
Write-Error "Could not find @1password/sdk in any node_modules directory"
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
$sdkPath = ($nodeModulesPath -replace '\\', '/') + "/@1password/sdk/dist/sdk.js"
|
|
89
|
+
|
|
90
|
+
# Get provider secrets from 1Password
|
|
91
|
+
Write-Info "Reading provider secrets from 1Password..."
|
|
92
|
+
|
|
93
|
+
$script = @"
|
|
94
|
+
const sdk = require('${sdkPath}');
|
|
95
|
+
|
|
96
|
+
async function getSecrets() {
|
|
97
|
+
const client = await sdk.createClient({
|
|
98
|
+
auth: '${Token}',
|
|
99
|
+
integrationName: 'opencode-1password-setup',
|
|
100
|
+
integrationVersion: '1.0.0'
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const providers = {};
|
|
104
|
+
const { variables: providerVars } = await client.environments.getVariables('${ProvidersEnvId}');
|
|
105
|
+
for (const v of providerVars) {
|
|
106
|
+
if (v.value) providers[v.name] = v.value;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const mcps = {};
|
|
110
|
+
if ('${McpsEnvId}') {
|
|
111
|
+
const { variables: mcpVars } = await client.environments.getVariables('${McpsEnvId}');
|
|
112
|
+
for (const v of mcpVars) {
|
|
113
|
+
if (v.value) mcps[v.name] = v.value;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log(JSON.stringify({ providers, mcps }));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getSecrets().catch(err => { console.error('FAILED:', err.message); process.exit(1); });
|
|
121
|
+
"@
|
|
122
|
+
|
|
123
|
+
$tempScript = [System.IO.Path]::GetTempFileName() -replace '\.tmp$', '.js'
|
|
124
|
+
$script | Out-File -FilePath $tempScript -Encoding UTF8 -NoNewline
|
|
125
|
+
|
|
126
|
+
$result = & node $tempScript 2>&1 | Out-String
|
|
127
|
+
Remove-Item $tempScript -ErrorAction SilentlyContinue
|
|
128
|
+
|
|
129
|
+
if ($result -match "FAILED:") {
|
|
130
|
+
Write-Error "Failed to read secrets from 1Password: $($result -replace 'FAILED:', '')"
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
$secrets = $result | ConvertFrom-Json
|
|
135
|
+
|
|
136
|
+
# Update auth.json
|
|
137
|
+
$authJsonPath = Get-OpenCodeAuthJsonPath
|
|
138
|
+
Write-Info "Updating auth.json..."
|
|
139
|
+
|
|
140
|
+
if (Test-Path $authJsonPath) {
|
|
141
|
+
$authContent = Get-Content $authJsonPath -Raw -Encoding UTF8
|
|
142
|
+
$auth = $authContent | ConvertFrom-Json
|
|
143
|
+
|
|
144
|
+
$modified = $false
|
|
145
|
+
foreach ($providerId in $auth.PSObject.Properties.Name) {
|
|
146
|
+
$authConfig = $auth.$providerId
|
|
147
|
+
if ($authConfig.key -and -not $authConfig.key.StartsWith("{env:")) {
|
|
148
|
+
$authConfig.key = "{env:$providerId}"
|
|
149
|
+
$modified = $true
|
|
150
|
+
Write-Success "Updated $providerId -> {env:$providerId}"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if ($modified) {
|
|
155
|
+
$auth | ConvertTo-Json -Depth 10 | Set-Content $authJsonPath -Encoding UTF8 -NoNewline
|
|
156
|
+
Write-Success "auth.json updated"
|
|
157
|
+
} else {
|
|
158
|
+
Write-Info "auth.json already uses environment variable references"
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
Write-Info "auth.json not found at $authJsonPath"
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
# Update opencode.json MCP config
|
|
165
|
+
$configJsonPath = Get-OpenCodeConfigJsonPath
|
|
166
|
+
Write-Info "Updating opencode.json MCP config..."
|
|
167
|
+
|
|
168
|
+
if (Test-Path $configJsonPath) {
|
|
169
|
+
$configContent = Get-Content $configJsonPath -Raw -Encoding UTF8
|
|
170
|
+
$config = $configContent | ConvertFrom-Json
|
|
171
|
+
|
|
172
|
+
$modified = $false
|
|
173
|
+
if ($config.mcp) {
|
|
174
|
+
foreach ($serverName in $config.mcp.PSObject.Properties.Name) {
|
|
175
|
+
$serverConfig = $config.mcp.$serverName
|
|
176
|
+
if ($serverConfig.environment) {
|
|
177
|
+
foreach ($key in $serverConfig.environment.PSObject.Properties.Name) {
|
|
178
|
+
$value = $serverConfig.environment.$key
|
|
179
|
+
if ($value -and -not $value.StartsWith("{env:") -and -not $value.StartsWith("$")) {
|
|
180
|
+
$serverConfig.environment.$key = "{env:$key}"
|
|
181
|
+
$modified = $true
|
|
182
|
+
Write-Success "Updated $serverName.$key -> {env:$key}"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if ($modified) {
|
|
190
|
+
$config | ConvertTo-Json -Depth 10 | Set-Content $configJsonPath -Encoding UTF8 -NoNewline
|
|
191
|
+
Write-Success "opencode.json updated"
|
|
192
|
+
} else {
|
|
193
|
+
Write-Info "opencode.json already uses environment variable references"
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
Write-Info "opencode.json not found at $configJsonPath"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
68
200
|
function Get-OpenCodeNodeModulesPath {
|
|
69
201
|
$paths = @(
|
|
70
202
|
"$env:USERPROFILE\.cache\opencode\node_modules",
|
|
@@ -320,6 +452,66 @@ if ($Audit) {
|
|
|
320
452
|
exit 0
|
|
321
453
|
}
|
|
322
454
|
|
|
455
|
+
if ($UpdateConfig) {
|
|
456
|
+
# Update Config mode
|
|
457
|
+
Write-Host "Update Config Mode" -ForegroundColor Yellow
|
|
458
|
+
Write-Host "------------------" -ForegroundColor Yellow
|
|
459
|
+
Write-Host ""
|
|
460
|
+
|
|
461
|
+
$token = Get-RegistryValue -Name "OP_SERVICE_ACCOUNT_TOKEN" -Scope "Machine"
|
|
462
|
+
$configId = Get-RegistryValue -Name "OP_CONFIG_ENV_ID" -Scope "Machine"
|
|
463
|
+
|
|
464
|
+
if (-not $token) {
|
|
465
|
+
$token = Get-RegistryValue -Name "OP_SERVICE_ACCOUNT_TOKEN" -Scope "User"
|
|
466
|
+
$configId = Get-RegistryValue -Name "OP_CONFIG_ENV_ID" -Scope "User"
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (-not $token -or -not $configId) {
|
|
470
|
+
Write-Error "Environment variables not set. Run setup first."
|
|
471
|
+
exit 1
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
Write-Info "Testing 1Password connection..."
|
|
475
|
+
|
|
476
|
+
if (Test-1PasswordConnection -Token $token) {
|
|
477
|
+
Write-Success "1Password connection successful!"
|
|
478
|
+
} else {
|
|
479
|
+
Write-Error "Failed to connect to 1Password. Check your service account token."
|
|
480
|
+
exit 1
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
Write-Info "Reading configuration from 1Password..."
|
|
484
|
+
|
|
485
|
+
$envIds = Get-1PasswordAudit -Token $token -ConfigEnvId $configId
|
|
486
|
+
|
|
487
|
+
if ($envIds) {
|
|
488
|
+
$providersEnvId = $null
|
|
489
|
+
$mcpsEnvId = $null
|
|
490
|
+
|
|
491
|
+
foreach ($prop in $envIds.PSObject.Properties) {
|
|
492
|
+
if ($prop.Name -eq "OPENCODE_PROVIDERS_ENV_ID") {
|
|
493
|
+
$providersEnvId = $prop.Value
|
|
494
|
+
} elseif ($prop.Name -eq "OPENCODE_MCPS_ENV_ID") {
|
|
495
|
+
$mcpsEnvId = $prop.Value
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if ($providersEnvId) {
|
|
500
|
+
Write-Info "Updating config files to use environment variables..."
|
|
501
|
+
Update-ConfigFiles -Token $token -ProvidersEnvId $providersEnvId -McpsEnvId $mcpsEnvId
|
|
502
|
+
Write-Success "Config update complete!"
|
|
503
|
+
} else {
|
|
504
|
+
Write-Error "Could not find OPENCODE_PROVIDERS_ENV_ID in bootstrap environment"
|
|
505
|
+
exit 1
|
|
506
|
+
}
|
|
507
|
+
} else {
|
|
508
|
+
Write-Error "Failed to read bootstrap environment."
|
|
509
|
+
exit 1
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
exit 0
|
|
513
|
+
}
|
|
514
|
+
|
|
323
515
|
# Setup mode (default)
|
|
324
516
|
Write-Host "Setup Mode" -ForegroundColor Yellow
|
|
325
517
|
Write-Host "----------" -ForegroundColor Yellow
|
|
@@ -438,6 +630,7 @@ Write-Success "Setup complete!"
|
|
|
438
630
|
Write-Info "Restart OpenCode to activate the plugin."
|
|
439
631
|
Write-Host ""
|
|
440
632
|
Write-Host "Usage:" -ForegroundColor White
|
|
441
|
-
Write-Host " ./setup.ps1 -Audit
|
|
442
|
-
Write-Host " ./setup.ps1 -
|
|
633
|
+
Write-Host " ./setup.ps1 -Audit Show current configuration"
|
|
634
|
+
Write-Host " ./setup.ps1 -UpdateConfig Update config files to use {env:VAR} references"
|
|
635
|
+
Write-Host " ./setup.ps1 -Uninstall Remove environment variables"
|
|
443
636
|
Write-Host ""
|
package/setup.sh
CHANGED
|
@@ -221,9 +221,161 @@ EOFINNER
|
|
|
221
221
|
done
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
update_config_files() {
|
|
225
|
+
local token="$1"
|
|
226
|
+
local providers_env_id="$2"
|
|
227
|
+
local mcps_env_id="$3"
|
|
228
|
+
|
|
229
|
+
log_info "Reading secrets from 1Password..."
|
|
230
|
+
|
|
231
|
+
# Get provider and MCP secrets
|
|
232
|
+
cat > /tmp/update_config_$$.js << 'EOF'
|
|
233
|
+
const sdk = require('@1password/sdk');
|
|
234
|
+
|
|
235
|
+
async function getSecrets() {
|
|
236
|
+
const token = process.argv[1];
|
|
237
|
+
const providersEnvId = process.argv[2];
|
|
238
|
+
const mcpsEnvId = process.argv[3];
|
|
239
|
+
|
|
240
|
+
const client = await sdk.createClient({
|
|
241
|
+
auth: token,
|
|
242
|
+
integrationName: 'opencode-1password-setup',
|
|
243
|
+
integrationVersion: '1.0.0'
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const providers = {};
|
|
247
|
+
const { variables: providerVars } = await client.environments.getVariables(providersEnvId);
|
|
248
|
+
for (const v of providerVars) {
|
|
249
|
+
if (v.value) providers[v.name] = v.value;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const mcps = {};
|
|
253
|
+
if (mcpsEnvId) {
|
|
254
|
+
const { variables: mcpVars } = await client.environments.getVariables(mcpsEnvId);
|
|
255
|
+
for (const v of mcpVars) {
|
|
256
|
+
if (v.value) mcps[v.name] = v.value;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
console.log(JSON.stringify({ providers, mcps }));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
getSecrets().catch(err => {
|
|
264
|
+
console.error('FAILED:', err.message);
|
|
265
|
+
process.exit(1);
|
|
266
|
+
});
|
|
267
|
+
EOF
|
|
268
|
+
|
|
269
|
+
result=$(node /tmp/update_config_$$.js "$token" "$providers_env_id" "$mcps_env_id" 2>&1)
|
|
270
|
+
rm -f /tmp/update_config_$$.js
|
|
271
|
+
|
|
272
|
+
if [[ "$result" == "FAILED:"* ]]; then
|
|
273
|
+
log_error "Failed to read secrets from 1Password: $result"
|
|
274
|
+
return 1
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# Get home directory
|
|
278
|
+
home="${HOME:-}"
|
|
279
|
+
if [[ -z "$home" ]]; then
|
|
280
|
+
home=$(eval echo ~)
|
|
281
|
+
fi
|
|
282
|
+
|
|
283
|
+
# Update auth.json
|
|
284
|
+
auth_json_path="$home/.local/share/opencode/auth.json"
|
|
285
|
+
log_info "Updating auth.json..."
|
|
286
|
+
|
|
287
|
+
if [[ -f "$auth_json_path" ]]; then
|
|
288
|
+
# Read auth.json and update
|
|
289
|
+
auth_content=$(cat "$auth_json_path")
|
|
290
|
+
# Use node to parse and update JSON
|
|
291
|
+
cat > /tmp/update_auth_$$.js << 'EOFJ'
|
|
292
|
+
const fs = require('fs');
|
|
293
|
+
const authPath = process.argv[1];
|
|
294
|
+
const auth = JSON.parse(fs.readFileSync(authPath, 'utf8'));
|
|
295
|
+
|
|
296
|
+
let modified = false;
|
|
297
|
+
for (const [providerId, authConfig] of Object.entries(auth)) {
|
|
298
|
+
if (authConfig.key && !authConfig.key.startsWith('{env:')) {
|
|
299
|
+
authConfig.key = '{env:' + providerId + '}';
|
|
300
|
+
modified = true;
|
|
301
|
+
console.log('Updated ' + providerId + ' -> {env:' + providerId + '}');
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (modified) {
|
|
306
|
+
fs.writeFileSync(authPath, JSON.stringify(auth, null, 2));
|
|
307
|
+
console.log('auth.json updated');
|
|
308
|
+
} else {
|
|
309
|
+
console.log('auth.json already uses environment variable references');
|
|
310
|
+
}
|
|
311
|
+
EOFJ
|
|
312
|
+
|
|
313
|
+
update_result=$(node /tmp/update_auth_$$.js "$auth_json_path" 2>&1)
|
|
314
|
+
rm -f /tmp/update_auth_$$.js
|
|
315
|
+
echo "$update_result" | while read line; do
|
|
316
|
+
if [[ "$line" == Updated* ]] || [[ "$line" == *updated* ]]; then
|
|
317
|
+
log_success "$(echo "$line" | sed 's/Updated/Updated/')"
|
|
318
|
+
else
|
|
319
|
+
log_info "$line"
|
|
320
|
+
fi
|
|
321
|
+
done
|
|
322
|
+
else
|
|
323
|
+
log_info "auth.json not found at $auth_json_path"
|
|
324
|
+
fi
|
|
325
|
+
|
|
326
|
+
# Update opencode.json MCP config
|
|
327
|
+
config_json_path="$home/.config/opencode/opencode.json"
|
|
328
|
+
log_info "Updating opencode.json MCP config..."
|
|
329
|
+
|
|
330
|
+
if [[ -f "$config_json_path" ]]; then
|
|
331
|
+
cat > /tmp/update_mcp_$$.js << 'EOFMCP'
|
|
332
|
+
const fs = require('fs');
|
|
333
|
+
const configPath = process.argv[1];
|
|
334
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
335
|
+
|
|
336
|
+
let modified = false;
|
|
337
|
+
if (config.mcp) {
|
|
338
|
+
for (const [serverName, serverConfig] of Object.entries(config.mcp)) {
|
|
339
|
+
if (serverConfig && serverConfig.environment) {
|
|
340
|
+
for (const [key, value] of Object.entries(serverConfig.environment)) {
|
|
341
|
+
if (value && !value.startsWith('{env:') && !value.startsWith('$')) {
|
|
342
|
+
serverConfig.environment[key] = '{env:' + key + '}';
|
|
343
|
+
modified = true;
|
|
344
|
+
console.log('Updated ' + serverName + '.' + key + ' -> {env:' + key + '}');
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (modified) {
|
|
352
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
353
|
+
console.log('opencode.json updated');
|
|
354
|
+
} else {
|
|
355
|
+
console.log('opencode.json already uses environment variable references');
|
|
356
|
+
}
|
|
357
|
+
EOFMCP
|
|
358
|
+
|
|
359
|
+
update_result=$(node /tmp/update_mcp_$$.js "$config_json_path" 2>&1)
|
|
360
|
+
rm -f /tmp/update_mcp_$$.js
|
|
361
|
+
echo "$update_result" | while read line; do
|
|
362
|
+
if [[ "$line" == Updated* ]] || [[ "$line" == *updated* ]]; then
|
|
363
|
+
log_success "$(echo "$line" | sed 's/Updated/Updated/')"
|
|
364
|
+
else
|
|
365
|
+
log_info "$line"
|
|
366
|
+
fi
|
|
367
|
+
done
|
|
368
|
+
else
|
|
369
|
+
log_info "opencode.json not found at $config_json_path"
|
|
370
|
+
fi
|
|
371
|
+
|
|
372
|
+
log_success "Config update complete!"
|
|
373
|
+
}
|
|
374
|
+
|
|
224
375
|
# Parse arguments
|
|
225
376
|
UNINSTALL=false
|
|
226
377
|
AUDIT=false
|
|
378
|
+
UPDATE_CONFIG=false
|
|
227
379
|
|
|
228
380
|
while [[ $# -gt 0 ]]; do
|
|
229
381
|
case $1 in
|
|
@@ -235,8 +387,12 @@ while [[ $# -gt 0 ]]; do
|
|
|
235
387
|
AUDIT=true
|
|
236
388
|
shift
|
|
237
389
|
;;
|
|
390
|
+
-c|--update-config)
|
|
391
|
+
UPDATE_CONFIG=true
|
|
392
|
+
shift
|
|
393
|
+
;;
|
|
238
394
|
*)
|
|
239
|
-
echo "Usage: $0 [--uninstall|--audit]"
|
|
395
|
+
echo "Usage: $0 [--uninstall|--audit|--update-config]"
|
|
240
396
|
exit 1
|
|
241
397
|
;;
|
|
242
398
|
esac
|
|
@@ -325,6 +481,51 @@ if [[ "$AUDIT" == true ]]; then
|
|
|
325
481
|
exit 0
|
|
326
482
|
fi
|
|
327
483
|
|
|
484
|
+
if [[ "$UPDATE_CONFIG" == true ]]; then
|
|
485
|
+
echo -e "${YELLOW}Update Config Mode${NC}"
|
|
486
|
+
echo -e "${YELLOW}------------------${NC}"
|
|
487
|
+
echo ""
|
|
488
|
+
|
|
489
|
+
get_existing_values
|
|
490
|
+
|
|
491
|
+
if [[ -z "$OP_SERVICE_ACCOUNT_TOKEN" || -z "$OP_CONFIG_ENV_ID" ]]; then
|
|
492
|
+
log_error "Environment variables not set. Run setup first."
|
|
493
|
+
exit 1
|
|
494
|
+
fi
|
|
495
|
+
|
|
496
|
+
log_info "Testing 1Password connection..."
|
|
497
|
+
|
|
498
|
+
if test_connection "$OP_SERVICE_ACCOUNT_TOKEN"; then
|
|
499
|
+
log_success "1Password connection successful!"
|
|
500
|
+
else
|
|
501
|
+
log_error "Failed to connect to 1Password. Check your service account token."
|
|
502
|
+
exit 1
|
|
503
|
+
fi
|
|
504
|
+
|
|
505
|
+
log_info "Reading configuration from 1Password..."
|
|
506
|
+
|
|
507
|
+
env_ids_json=$(get_audit_data "$OP_SERVICE_ACCOUNT_TOKEN" "$OP_CONFIG_ENV_ID")
|
|
508
|
+
|
|
509
|
+
if [[ -n "$env_ids_json" && "$env_ids_json" != "FAILED:"* ]]; then
|
|
510
|
+
# Parse JSON to extract env IDs
|
|
511
|
+
providers_env_id=$(echo "$env_ids_json" | sed -n 's/.*"OPENCODE_PROVIDERS_ENV_ID":"\([^"]*\)".*/\1/p')
|
|
512
|
+
mcps_env_id=$(echo "$env_ids_json" | sed -n 's/.*"OPENCODE_MCPS_ENV_ID":"\([^"]*\)".*/\1/p')
|
|
513
|
+
|
|
514
|
+
if [[ -n "$providers_env_id" ]]; then
|
|
515
|
+
log_info "Updating config files to use environment variables..."
|
|
516
|
+
update_config_files "$OP_SERVICE_ACCOUNT_TOKEN" "$providers_env_id" "$mcps_env_id"
|
|
517
|
+
else
|
|
518
|
+
log_error "Could not find OPENCODE_PROVIDERS_ENV_ID in bootstrap environment"
|
|
519
|
+
exit 1
|
|
520
|
+
fi
|
|
521
|
+
else
|
|
522
|
+
log_error "Failed to read bootstrap environment."
|
|
523
|
+
exit 1
|
|
524
|
+
fi
|
|
525
|
+
|
|
526
|
+
exit 0
|
|
527
|
+
fi
|
|
528
|
+
|
|
328
529
|
# Setup mode (default)
|
|
329
530
|
echo -e "${YELLOW}Setup Mode${NC}"
|
|
330
531
|
echo -e "${YELLOW}----------${NC}"
|
|
@@ -439,6 +640,7 @@ log_success "Setup complete!"
|
|
|
439
640
|
log_info "Restart OpenCode to activate the plugin."
|
|
440
641
|
echo ""
|
|
441
642
|
echo "Usage:"
|
|
442
|
-
echo " ./setup.sh --audit
|
|
443
|
-
echo " ./setup.sh --
|
|
643
|
+
echo " ./setup.sh --audit Show current configuration"
|
|
644
|
+
echo " ./setup.sh --update-config Update config files to use {env:VAR} references"
|
|
645
|
+
echo " ./setup.sh --uninstall Remove environment variables"
|
|
444
646
|
echo ""
|