@askalf/dario 3.9.0 → 3.9.2
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/dist/cli.js +5 -10
- package/dist/oauth.js +69 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -373,18 +373,13 @@ async function help() {
|
|
|
373
373
|
Full IDs: claude-opus-4-6, claude-sonnet-4-6
|
|
374
374
|
Default: passthrough (client decides)
|
|
375
375
|
--passthrough, --thin Thin proxy — OAuth swap only, no injection
|
|
376
|
-
--preserve-tools
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
from CC's. Preserves CC fingerprint. See #33.
|
|
376
|
+
--preserve-tools Forward client tool schemas unchanged
|
|
377
|
+
Loses subscription routing; use for custom agents
|
|
378
|
+
--hybrid-tools Remap to CC tools, inject sessionId/requestId/etc.
|
|
379
|
+
Keeps subscription routing for custom agents
|
|
381
380
|
--port=PORT Port to listen on (default: 3456)
|
|
382
381
|
--host=ADDRESS Address to bind to (default: 127.0.0.1)
|
|
383
|
-
Use 0.0.0.0
|
|
384
|
-
Alternatively set DARIO_HOST env var.
|
|
385
|
-
When binding non-loopback, also set DARIO_API_KEY
|
|
386
|
-
so unauthenticated LAN hosts can't proxy through
|
|
387
|
-
your OAuth subscription.
|
|
382
|
+
Use 0.0.0.0 for LAN; see README for DARIO_API_KEY
|
|
388
383
|
--verbose, -v Log all requests
|
|
389
384
|
|
|
390
385
|
Quick start:
|
package/dist/oauth.js
CHANGED
|
@@ -52,8 +52,47 @@ function getClaudeCodeCredentialsPath() {
|
|
|
52
52
|
* store instead of ~/.claude/.credentials.json:
|
|
53
53
|
* - macOS: Keychain, service "Claude Code-credentials"
|
|
54
54
|
* - Linux: libsecret / Secret Service D-Bus API via `secret-tool`
|
|
55
|
-
* - Windows: Windows Credential Manager via
|
|
55
|
+
* - Windows: Windows Credential Manager via PowerShell + Win32 CredEnumerate
|
|
56
56
|
*/
|
|
57
|
+
const WIN_CRED_SCRIPT = `
|
|
58
|
+
$ErrorActionPreference = 'Stop'
|
|
59
|
+
$sig = @"
|
|
60
|
+
using System;
|
|
61
|
+
using System.Runtime.InteropServices;
|
|
62
|
+
public class CM {
|
|
63
|
+
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
|
|
64
|
+
public struct CRED {
|
|
65
|
+
public uint Flags; public uint Type; public string TargetName;
|
|
66
|
+
public string Comment; public System.Runtime.InteropServices.ComTypes.FILETIME LW;
|
|
67
|
+
public uint BlobSize; public IntPtr Blob;
|
|
68
|
+
public uint Persist; public uint AC; public IntPtr Attrs;
|
|
69
|
+
public string Alias; public string UN;
|
|
70
|
+
}
|
|
71
|
+
[DllImport("advapi32.dll", EntryPoint="CredEnumerateW", CharSet=CharSet.Unicode, SetLastError=true)]
|
|
72
|
+
public static extern bool CredEnumerate(string filter, uint flag, out uint count, out IntPtr pCredentials);
|
|
73
|
+
[DllImport("advapi32.dll", EntryPoint="CredFree")]
|
|
74
|
+
public static extern void CredFree(IntPtr cred);
|
|
75
|
+
}
|
|
76
|
+
"@
|
|
77
|
+
Add-Type -TypeDefinition $sig
|
|
78
|
+
$count = 0
|
|
79
|
+
$ptr = [IntPtr]::Zero
|
|
80
|
+
if ([CM]::CredEnumerate('Claude Code-credentials*', 0, [ref]$count, [ref]$ptr)) {
|
|
81
|
+
try {
|
|
82
|
+
for ($i = 0; $i -lt $count; $i++) {
|
|
83
|
+
$credPtr = [System.Runtime.InteropServices.Marshal]::ReadIntPtr($ptr, $i * [IntPtr]::Size)
|
|
84
|
+
$cred = [System.Runtime.InteropServices.Marshal]::PtrToStructure($credPtr, [type][CM+CRED])
|
|
85
|
+
if ($cred.BlobSize -gt 0) {
|
|
86
|
+
$bytes = New-Object byte[] $cred.BlobSize
|
|
87
|
+
[System.Runtime.InteropServices.Marshal]::Copy($cred.Blob, $bytes, 0, $cred.BlobSize)
|
|
88
|
+
Write-Output ([System.Text.Encoding]::Unicode.GetString($bytes))
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
} finally {
|
|
92
|
+
[CM]::CredFree($ptr)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
57
96
|
async function loadKeychainCredentials() {
|
|
58
97
|
try {
|
|
59
98
|
if (platform() === 'darwin') {
|
|
@@ -74,6 +113,35 @@ async function loadKeychainCredentials() {
|
|
|
74
113
|
return parsed;
|
|
75
114
|
}
|
|
76
115
|
}
|
|
116
|
+
else if (platform() === 'win32') {
|
|
117
|
+
// Windows Credential Manager via PowerShell + Win32 CredEnumerate.
|
|
118
|
+
// Claude Code on Windows (via Node keytar) stores OAuth tokens as
|
|
119
|
+
// Generic credentials with target prefix "Claude Code-credentials".
|
|
120
|
+
// We enumerate matching credentials and return the first one that
|
|
121
|
+
// parses as a valid CC credentials blob. The password field is
|
|
122
|
+
// stored as UTF-16LE bytes (keytar convention on Windows).
|
|
123
|
+
//
|
|
124
|
+
// PowerShell CredEnumerate sets LastWin32Error=1168 (ERROR_NOT_FOUND)
|
|
125
|
+
// when the filter matches nothing — we catch the non-zero exit and
|
|
126
|
+
// return null so the caller falls back to the file-path checks.
|
|
127
|
+
const raw = await new Promise((resolve, reject) => {
|
|
128
|
+
execFile('powershell.exe', ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', WIN_CRED_SCRIPT], { timeout: 5000, windowsHide: true }, (err, stdout) => (err ? reject(err) : resolve(stdout)));
|
|
129
|
+
});
|
|
130
|
+
// Script emits one JSON blob per matching credential, newline-separated.
|
|
131
|
+
// Return the first one that parses with the expected CC shape.
|
|
132
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
133
|
+
const s = line.trim();
|
|
134
|
+
if (!s)
|
|
135
|
+
continue;
|
|
136
|
+
try {
|
|
137
|
+
const parsed = JSON.parse(s);
|
|
138
|
+
if (parsed?.claudeAiOauth?.accessToken && parsed?.claudeAiOauth?.refreshToken) {
|
|
139
|
+
return parsed;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch { /* not a valid JSON credential blob — try next */ }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
77
145
|
}
|
|
78
146
|
catch { /* keychain not available or no entry */ }
|
|
79
147
|
return null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askalf/dario",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.2",
|
|
4
4
|
"description": "A local LLM router. One endpoint, every provider — Claude subscriptions, OpenAI, OpenRouter, Groq, local LiteLLM, any OpenAI-compat endpoint — your tools don't need to change.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|