@goodandready/dsh-subscriptions 0.5.6 → 0.5.21
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/atomic-lock.js +35 -0
- package/lib/backoff.js +26 -0
- package/lib/client.js +211 -15
- package/lib/coalesce-stream.js +22 -0
- package/lib/code-assist.js +4 -4
- package/lib/cookie-bridge.js +8 -0
- package/lib/credit-detect.js +22 -0
- package/lib/encrypted-bundle.js +46 -0
- package/lib/import-auth.js +74 -7
- package/lib/importers/coding-agents.js +37 -0
- package/lib/index.js +35 -7
- package/lib/latency-heatmap.js +26 -0
- package/lib/latency-score.js +36 -0
- package/lib/multi-tenant.js +16 -0
- package/lib/network-benchmark.js +23 -0
- package/lib/pkce-store.js +28 -0
- package/lib/preflight-tokens.js +23 -0
- package/lib/proactive-refresh.js +37 -0
- package/lib/prompt-cache-warmer.js +44 -0
- package/lib/quarantine.js +38 -0
- package/lib/ratelimit-parser.js +24 -0
- package/lib/reconnect-stream.js +21 -0
- package/lib/reset-toast.js +38 -0
- package/lib/revocation.js +25 -0
- package/lib/rotate.js +70 -17
- package/lib/savings-calculator.js +14 -0
- package/lib/session-pin.js +29 -0
- package/lib/state-recovery.js +33 -0
- package/lib/stream-rotate.js +34 -11
- package/lib/telemetry.js +28 -0
- package/lib/token-speedometer.js +26 -0
- package/lib/vendors/antigravity.js +18 -5
- package/lib/vendors/claude-cli.js +24 -0
- package/lib/vendors/cody.js +72 -0
- package/lib/vendors/copilot.js +194 -0
- package/lib/vendors/cursor.js +1 -1
- package/lib/vendors/ernie.js +93 -0
- package/lib/vendors/glm.js +1 -1
- package/lib/vendors/index.js +26 -1
- package/lib/vendors/jetbrains.js +79 -0
- package/lib/vendors/kimi.js +1 -1
- package/lib/vendors/perplexity.js +79 -0
- package/lib/vendors/qwen.js +89 -0
- package/lib/vendors/replit.js +72 -0
- package/lib/vendors/spark.js +77 -0
- package/lib/wire.js +4 -2
- package/lib/zero-trace-logger.js +27 -0
- package/package.json +2 -5
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { LlmError } from '@deepseek-ai/dsh-llm'
|
|
2
|
+
import { openaiMessages } from '../messages.js'
|
|
3
|
+
import { openaiChatStream, httpError } from '../wire.js'
|
|
4
|
+
import { asUsageSnapshot } from '../usage.js'
|
|
5
|
+
|
|
6
|
+
export const id = 'jetbrains'
|
|
7
|
+
export const JETBRAINS_API_BASE = 'https://api.jetbrains.ai'
|
|
8
|
+
|
|
9
|
+
export const JETBRAINS_MODELS = [
|
|
10
|
+
{
|
|
11
|
+
id: 'jb-claude-3.5-sonnet',
|
|
12
|
+
name: 'Claude 3.5 Sonnet (JetBrains AI)',
|
|
13
|
+
contextWindow: 200000,
|
|
14
|
+
maxTokens: 8192,
|
|
15
|
+
inputModalities: ['text']
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'jb-gpt-4o',
|
|
19
|
+
name: 'GPT-4o (JetBrains AI)',
|
|
20
|
+
contextWindow: 128000,
|
|
21
|
+
maxTokens: 8192,
|
|
22
|
+
inputModalities: ['text']
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
export function providerInfo() {
|
|
27
|
+
return { id, name: 'JetBrains AI' }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function defaults() {
|
|
31
|
+
return {
|
|
32
|
+
apiBase: JETBRAINS_API_BASE,
|
|
33
|
+
models: JETBRAINS_MODELS.map((m) => m.id)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function authorizeUrl() {
|
|
38
|
+
return 'https://account.jetbrains.com/'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function listModels() {
|
|
42
|
+
return JETBRAINS_MODELS
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function usage(blob) {
|
|
46
|
+
if (blob && (blob.accessToken || blob.token)) {
|
|
47
|
+
return asUsageSnapshot(30)
|
|
48
|
+
}
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
53
|
+
const impl = fetchImpl || fetch
|
|
54
|
+
const token = blob && (blob.accessToken || blob.token)
|
|
55
|
+
if (!token) throw new LlmError('JetBrains AI Assistant not authenticated', 'AUTH')
|
|
56
|
+
|
|
57
|
+
const url = `${(config && config.apiBase) || JETBRAINS_API_BASE}/v1/chat/completions`
|
|
58
|
+
const model = (options.model || 'jb-claude-3.5-sonnet').replace(/^jb-/, '')
|
|
59
|
+
const body = {
|
|
60
|
+
model,
|
|
61
|
+
messages: openaiMessages(options),
|
|
62
|
+
stream: true
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const res = await impl(url, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
...headers,
|
|
69
|
+
'Authorization': `Bearer ${token}`,
|
|
70
|
+
'Content-Type': 'application/json',
|
|
71
|
+
'User-Agent': 'IntelliJ-IDEA/2026.1'
|
|
72
|
+
},
|
|
73
|
+
body: JSON.stringify(body),
|
|
74
|
+
signal
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
if (!res.ok) throw httpError(res.status, await res.text())
|
|
78
|
+
yield* openaiChatStream(res.body)
|
|
79
|
+
}
|
package/lib/vendors/kimi.js
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { LlmError } from '@deepseek-ai/dsh-llm'
|
|
2
|
+
import { openaiMessages } from '../messages.js'
|
|
3
|
+
import { openaiChatStream, httpError } from '../wire.js'
|
|
4
|
+
import { asUsageSnapshot } from '../usage.js'
|
|
5
|
+
|
|
6
|
+
export const id = 'perplexity'
|
|
7
|
+
export const PERPLEXITY_API_BASE = 'https://api.perplexity.ai'
|
|
8
|
+
|
|
9
|
+
export const PERPLEXITY_MODELS = [
|
|
10
|
+
{
|
|
11
|
+
id: 'sonar-reasoning-pro',
|
|
12
|
+
name: 'Sonar Reasoning Pro',
|
|
13
|
+
contextWindow: 128000,
|
|
14
|
+
maxTokens: 8192,
|
|
15
|
+
inputModalities: ['text']
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'sonar-pro',
|
|
19
|
+
name: 'Sonar Pro',
|
|
20
|
+
contextWindow: 200000,
|
|
21
|
+
maxTokens: 8192,
|
|
22
|
+
inputModalities: ['text']
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
export function providerInfo() {
|
|
27
|
+
return { id, name: 'Perplexity Pro' }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function defaults() {
|
|
31
|
+
return {
|
|
32
|
+
apiBase: PERPLEXITY_API_BASE,
|
|
33
|
+
models: PERPLEXITY_MODELS.map((m) => m.id)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function authorizeUrl() {
|
|
38
|
+
return 'https://www.perplexity.ai/settings/api'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function listModels() {
|
|
42
|
+
return PERPLEXITY_MODELS
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function usage(blob) {
|
|
46
|
+
if (blob && (blob.accessToken || blob.apiKey)) {
|
|
47
|
+
const snap = asUsageSnapshot(18)
|
|
48
|
+
if (snap) snap.plan = 'Perplexity Pro'
|
|
49
|
+
return snap
|
|
50
|
+
}
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
55
|
+
const impl = fetchImpl || fetch
|
|
56
|
+
const key = blob && (blob.accessToken || blob.apiKey)
|
|
57
|
+
if (!key) throw new LlmError('Perplexity API key or session token required', 'AUTH')
|
|
58
|
+
|
|
59
|
+
const url = `${(config && config.apiBase) || PERPLEXITY_API_BASE}/chat/completions`
|
|
60
|
+
const body = {
|
|
61
|
+
model: options.model || 'sonar-pro',
|
|
62
|
+
messages: openaiMessages(options),
|
|
63
|
+
stream: true
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const res = await impl(url, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
headers: {
|
|
69
|
+
...headers,
|
|
70
|
+
'Authorization': `Bearer ${key}`,
|
|
71
|
+
'Content-Type': 'application/json'
|
|
72
|
+
},
|
|
73
|
+
body: JSON.stringify(body),
|
|
74
|
+
signal
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
if (!res.ok) throw httpError(res.status, await res.text())
|
|
78
|
+
yield* openaiChatStream(res.body)
|
|
79
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { LlmError } from '@deepseek-ai/dsh-llm'
|
|
2
|
+
import { openaiMessages, openaiTools } from '../messages.js'
|
|
3
|
+
import { openaiChatStream, readJson, httpError } from '../wire.js'
|
|
4
|
+
import { asUsageSnapshot } from '../usage.js'
|
|
5
|
+
|
|
6
|
+
export const id = 'qwen'
|
|
7
|
+
export const QWEN_API_BASE = 'https://dashscope.aliyuncs.com/compatible-mode/v1'
|
|
8
|
+
|
|
9
|
+
export const QWEN_MODELS = [
|
|
10
|
+
{
|
|
11
|
+
id: 'qwen-2.5-coder-32b-instruct',
|
|
12
|
+
name: 'Qwen 2.5 Coder 32B',
|
|
13
|
+
contextWindow: 131072,
|
|
14
|
+
maxTokens: 8192,
|
|
15
|
+
inputModalities: ['text']
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'qwen-max-latest',
|
|
19
|
+
name: 'Qwen Max',
|
|
20
|
+
contextWindow: 32768,
|
|
21
|
+
maxTokens: 8192,
|
|
22
|
+
inputModalities: ['text']
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'qwen-plus-latest',
|
|
26
|
+
name: 'Qwen Plus',
|
|
27
|
+
contextWindow: 131072,
|
|
28
|
+
maxTokens: 8192,
|
|
29
|
+
inputModalities: ['text']
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
export function providerInfo() {
|
|
34
|
+
return { id, name: 'Alibaba Qwen' }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function defaults() {
|
|
38
|
+
return {
|
|
39
|
+
apiBase: QWEN_API_BASE,
|
|
40
|
+
models: QWEN_MODELS.map((m) => m.id)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function authorizeUrl() {
|
|
45
|
+
return 'https://bailian.console.aliyun.com/'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function listModels() {
|
|
49
|
+
return QWEN_MODELS
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function usage(blob) {
|
|
53
|
+
if (blob && (blob.accessToken || blob.apiKey)) {
|
|
54
|
+
return asUsageSnapshot(15)
|
|
55
|
+
}
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
60
|
+
const impl = fetchImpl || fetch
|
|
61
|
+
const key = blob && (blob.accessToken || blob.apiKey)
|
|
62
|
+
if (!key) throw new LlmError('Qwen API Key or Token is required', 'AUTH')
|
|
63
|
+
|
|
64
|
+
const body = {
|
|
65
|
+
model: options.model || 'qwen-2.5-coder-32b-instruct',
|
|
66
|
+
messages: openaiMessages(options),
|
|
67
|
+
stream: true,
|
|
68
|
+
...(options.maxTokens != null ? { max_tokens: options.maxTokens } : {}),
|
|
69
|
+
...(options.temperature != null ? { temperature: options.temperature } : {})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const tools = openaiTools(options)
|
|
73
|
+
if (tools && tools.length) body.tools = tools
|
|
74
|
+
|
|
75
|
+
const url = ((config && config.apiBase) || QWEN_API_BASE).replace(/\/+$/, '') + '/chat/completions'
|
|
76
|
+
const res = await impl(url, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: {
|
|
79
|
+
...headers,
|
|
80
|
+
'Authorization': `Bearer ${key}`,
|
|
81
|
+
'Content-Type': 'application/json'
|
|
82
|
+
},
|
|
83
|
+
body: JSON.stringify(body),
|
|
84
|
+
signal
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
if (!res.ok) throw httpError(res.status, await res.text())
|
|
88
|
+
yield* openaiChatStream(res.body)
|
|
89
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { LlmError } from '@deepseek-ai/dsh-llm'
|
|
2
|
+
import { openaiMessages } from '../messages.js'
|
|
3
|
+
import { openaiChatStream, httpError } from '../wire.js'
|
|
4
|
+
import { asUsageSnapshot } from '../usage.js'
|
|
5
|
+
|
|
6
|
+
export const id = 'replit'
|
|
7
|
+
export const REPLIT_API_BASE = 'https://replit.com/api/v1/ai'
|
|
8
|
+
|
|
9
|
+
export const REPLIT_MODELS = [
|
|
10
|
+
{
|
|
11
|
+
id: 'replit-code-v2',
|
|
12
|
+
name: 'Replit Code Agent V2',
|
|
13
|
+
contextWindow: 128000,
|
|
14
|
+
maxTokens: 8192,
|
|
15
|
+
inputModalities: ['text']
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
export function providerInfo() {
|
|
20
|
+
return { id, name: 'Replit Core' }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function defaults() {
|
|
24
|
+
return {
|
|
25
|
+
apiBase: REPLIT_API_BASE,
|
|
26
|
+
models: REPLIT_MODELS.map((m) => m.id)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function authorizeUrl() {
|
|
31
|
+
return 'https://replit.com/account'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function listModels() {
|
|
35
|
+
return REPLIT_MODELS
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function usage(blob) {
|
|
39
|
+
if (blob && (blob.accessToken || blob.token)) {
|
|
40
|
+
const snap = asUsageSnapshot(25)
|
|
41
|
+
if (snap) snap.plan = 'Replit Core'
|
|
42
|
+
return snap
|
|
43
|
+
}
|
|
44
|
+
return null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
48
|
+
const impl = fetchImpl || fetch
|
|
49
|
+
const token = blob && (blob.accessToken || blob.token)
|
|
50
|
+
if (!token) throw new LlmError('Replit Core not authenticated', 'AUTH')
|
|
51
|
+
|
|
52
|
+
const url = `${(config && config.apiBase) || REPLIT_API_BASE}/chat/completions`
|
|
53
|
+
const body = {
|
|
54
|
+
model: options.model || 'replit-code-v2',
|
|
55
|
+
messages: openaiMessages(options),
|
|
56
|
+
stream: true
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const res = await impl(url, {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: {
|
|
62
|
+
...headers,
|
|
63
|
+
'Authorization': `Bearer ${token}`,
|
|
64
|
+
'Content-Type': 'application/json'
|
|
65
|
+
},
|
|
66
|
+
body: JSON.stringify(body),
|
|
67
|
+
signal
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
if (!res.ok) throw httpError(res.status, await res.text())
|
|
71
|
+
yield* openaiChatStream(res.body)
|
|
72
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LlmError } from '@deepseek-ai/dsh-llm'
|
|
2
|
+
import { openaiMessages } from '../messages.js'
|
|
3
|
+
import { openaiChatStream, readJson, httpError } from '../wire.js'
|
|
4
|
+
import { asUsageSnapshot } from '../usage.js'
|
|
5
|
+
|
|
6
|
+
export const id = 'spark'
|
|
7
|
+
export const SPARK_API_BASE = 'https://spark-api-open.xf-yun.com/v1'
|
|
8
|
+
|
|
9
|
+
export const SPARK_MODELS = [
|
|
10
|
+
{
|
|
11
|
+
id: 'spark-max',
|
|
12
|
+
name: 'iFlytek Spark Max',
|
|
13
|
+
contextWindow: 32768,
|
|
14
|
+
maxTokens: 8192,
|
|
15
|
+
inputModalities: ['text']
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'spark-lite',
|
|
19
|
+
name: 'iFlytek Spark Lite',
|
|
20
|
+
contextWindow: 8192,
|
|
21
|
+
maxTokens: 4096,
|
|
22
|
+
inputModalities: ['text']
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
export function providerInfo() {
|
|
27
|
+
return { id, name: 'iFlytek Spark' }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function defaults() {
|
|
31
|
+
return {
|
|
32
|
+
apiBase: SPARK_API_BASE,
|
|
33
|
+
models: SPARK_MODELS.map((m) => m.id)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function authorizeUrl() {
|
|
38
|
+
return 'https://xinghuo.xfyun.cn/'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function listModels() {
|
|
42
|
+
return SPARK_MODELS
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function usage(blob) {
|
|
46
|
+
if (blob && (blob.accessToken || blob.apiKey)) {
|
|
47
|
+
return asUsageSnapshot(12)
|
|
48
|
+
}
|
|
49
|
+
return null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
|
|
53
|
+
const impl = fetchImpl || fetch
|
|
54
|
+
const key = blob && (blob.accessToken || blob.apiKey)
|
|
55
|
+
if (!key) throw new LlmError('iFlytek Spark requires API key', 'AUTH')
|
|
56
|
+
|
|
57
|
+
const url = `${(config && config.apiBase) || SPARK_API_BASE}/chat/completions`
|
|
58
|
+
const body = {
|
|
59
|
+
model: options.model || 'spark-max',
|
|
60
|
+
messages: openaiMessages(options),
|
|
61
|
+
stream: true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const res = await impl(url, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: {
|
|
67
|
+
...headers,
|
|
68
|
+
'Authorization': `Bearer ${key}`,
|
|
69
|
+
'Content-Type': 'application/json'
|
|
70
|
+
},
|
|
71
|
+
body: JSON.stringify(body),
|
|
72
|
+
signal
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
if (!res.ok) throw httpError(res.status, await res.text())
|
|
76
|
+
yield* openaiChatStream(res.body)
|
|
77
|
+
}
|
package/lib/wire.js
CHANGED
|
@@ -182,7 +182,8 @@ export async function* googleStream(body) {
|
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
export async function formTokenRequest(url, params, fetchImpl, headers) {
|
|
185
|
-
const
|
|
185
|
+
const impl = fetchImpl || fetch
|
|
186
|
+
const res = await impl(url, {
|
|
186
187
|
method: 'POST',
|
|
187
188
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded', Accept: 'application/json', ...(headers || {}) },
|
|
188
189
|
body: new URLSearchParams(params),
|
|
@@ -191,7 +192,8 @@ export async function formTokenRequest(url, params, fetchImpl, headers) {
|
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
export async function jsonTokenRequest(url, body, fetchImpl, headers) {
|
|
194
|
-
const
|
|
195
|
+
const impl = fetchImpl || fetch
|
|
196
|
+
const res = await impl(url, {
|
|
195
197
|
method: 'POST',
|
|
196
198
|
headers: { 'Content-Type': 'application/json', Accept: 'application/json', ...(headers || {}) },
|
|
197
199
|
body: JSON.stringify(body),
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const SENSITIVE_PATTERNS = [
|
|
2
|
+
/Bearer\s+([^\s,"'}]+)/gi,
|
|
3
|
+
/(access_token|refresh_token|token|api_key|secret|password|authorization)=([^&\s]+)/gi,
|
|
4
|
+
/("?(?:accessToken|refreshToken|apiKey|secretKey|token)"?\s*:\s*")([^"]+)(")/gi
|
|
5
|
+
]
|
|
6
|
+
|
|
7
|
+
export function sanitizeLogText(text) {
|
|
8
|
+
if (typeof text !== 'string') {
|
|
9
|
+
try {
|
|
10
|
+
text = JSON.stringify(text)
|
|
11
|
+
} catch {
|
|
12
|
+
return '[Unserializable]'
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let sanitized = text
|
|
17
|
+
// 1. Bearer
|
|
18
|
+
sanitized = sanitized.replace(/Bearer\s+([^\s,"'}]+)/gi, 'Bearer ***MASKED***')
|
|
19
|
+
|
|
20
|
+
// 2. Query param style
|
|
21
|
+
sanitized = sanitized.replace(/(access_token|refresh_token|token|api_key|secret|password|authorization)=([^&\s]+)/gi, '$1=***MASKED***')
|
|
22
|
+
|
|
23
|
+
// 3. JSON key style
|
|
24
|
+
sanitized = sanitized.replace(/("?(?:accessToken|refreshToken|apiKey|secretKey|token)"?\s*:\s*")([^"]+)(")/gi, '$1***MASKED***$3')
|
|
25
|
+
|
|
26
|
+
return sanitized
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-subscriptions",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.21",
|
|
4
4
|
"description": "Use ChatGPT Codex, Claude, Grok, and Antigravity subscriptions as DeepSeek Harness LLM providers via OAuth.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -43,10 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"client": {
|
|
45
45
|
"platform": "web",
|
|
46
|
-
"inject": [
|
|
47
|
-
"@deepseek-ai/dsh-client-runtime",
|
|
48
|
-
"@deepseek-ai/dsh-client-ui-slots"
|
|
49
|
-
]
|
|
46
|
+
"inject": []
|
|
50
47
|
}
|
|
51
48
|
},
|
|
52
49
|
"peerDependencies": {
|