@goodandready/dsh-clinebot 0.5.33 → 0.6.1

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.
@@ -1,84 +1,104 @@
1
- /**
2
- * Credentials management helper for @goodandready/dsh-clinebot.
3
- * Isolates DSH Credentials storage and environment resolution.
4
- */
5
-
6
- export const DEFAULT_API_KEY_ENV = 'CLINEBOT_API_KEY'
7
-
8
- export async function toCredentialRef(name) {
9
- try {
10
- const mod = await import('@deepseek-ai/dsh-credentials')
11
- if (typeof mod.credentialRef === 'function') {
12
- return mod.credentialRef(name)
13
- }
14
- } catch {
15
- /* fallback when executed in standalone unit tests outside DSH bundle */
16
- }
17
- return typeof name === 'object' && name !== null ? name : { type: 'env', name: String(name || '') }
18
- }
19
-
20
- export function resolveApiKey(apiKeyEnv, env = process.env) {
21
- const name = String(apiKeyEnv || DEFAULT_API_KEY_ENV).trim() || DEFAULT_API_KEY_ENV
22
- return {
23
- envName: name,
24
- value: String(env[name] || ''),
25
- }
26
- }
27
-
28
- export async function saveCredentialKey(ctx, apiKeyEnv, apiKey) {
29
- const name = String(apiKeyEnv || DEFAULT_API_KEY_ENV).trim() || DEFAULT_API_KEY_ENV
30
- const value = String(apiKey || '').trim()
31
-
32
- if (!value) {
33
- throw new Error('API key cannot be empty')
34
- }
35
-
36
- const credentials = ctx?.credentials || ctx?.get?.('credentials')
37
- if (!credentials || typeof credentials.set !== 'function') {
38
- throw new Error('DSH credentials service is unavailable in this runtime profile')
39
- }
40
-
41
- const ref = await toCredentialRef(name)
42
- await credentials.set(ref, value)
43
- return { ok: true, envName: name }
44
- }
45
-
46
- export async function deleteCredentialKey(ctx, apiKeyEnv) {
47
- const name = String(apiKeyEnv || '').trim()
48
- if (!name) return { ok: false }
49
- const credentials = ctx?.credentials || ctx?.get?.('credentials')
50
- if (!credentials) return { ok: false }
51
- try {
52
- const ref = await toCredentialRef(name)
53
- if (typeof credentials.unset === 'function') {
54
- await credentials.unset(ref)
55
- return { ok: true, envName: name }
56
- }
57
- } catch (err) {
58
- ctx?.logger?.warn?.('[dsh-clinebot] Failed unsetting credential: ' + (err?.message || err))
59
- }
60
- return { ok: false }
61
- }
62
-
63
- export async function resolveKeyValue(ctx, apiKeyEnv) {
64
- const refName = String(apiKeyEnv || DEFAULT_API_KEY_ENV).trim() || DEFAULT_API_KEY_ENV
65
- const creds = (ctx?.get && ctx.get('credentials')) || ctx?.credentials
66
- if (creds && typeof creds.resolve === 'function') {
67
- try {
68
- const ref = await toCredentialRef(refName)
69
- const hit = await creds.resolve(ref)
70
- if (hit?.value) {
71
- return { envName: refName, value: hit.value, source: 'credentials' }
72
- }
73
- } catch {
74
- /* miss */
75
- }
76
- }
77
-
78
- const fromEnv = resolveApiKey(refName)
79
- if (fromEnv.value) {
80
- return { ...fromEnv, source: 'env' }
81
- }
82
-
83
- return { envName: refName, value: '', source: 'none' }
84
- }
1
+ /**
2
+ * Credentials management helper for @goodandready/dsh-clinebot.
3
+ * Isolates DSH Credentials storage and environment resolution.
4
+ */
5
+
6
+ export const DEFAULT_API_KEY_ENV = 'CLINEBOT_API_KEY'
7
+
8
+ /**
9
+ * Resolve the optional credentials service without tripping Cordis's
10
+ * strict-proxy guard on undeclared property reads.
11
+ * @param {object | undefined} ctx
12
+ * @returns {object | undefined}
13
+ */
14
+ function credentialsService(ctx) {
15
+ try {
16
+ const viaGet = typeof ctx?.get === 'function' ? ctx.get('credentials') : undefined
17
+ if (viaGet) return viaGet
18
+ } catch {
19
+ /* strict context refuses get() for a service the fiber does not inject */
20
+ }
21
+ try {
22
+ return ctx ? ctx.credentials : undefined
23
+ } catch {
24
+ return undefined
25
+ }
26
+ }
27
+
28
+ export async function toCredentialRef(name) {
29
+ try {
30
+ const mod = await import('@deepseek-ai/dsh-credentials')
31
+ if (typeof mod.credentialRef === 'function') {
32
+ return mod.credentialRef(name)
33
+ }
34
+ } catch {
35
+ /* fallback when executed in standalone unit tests outside DSH bundle */
36
+ }
37
+ return typeof name === 'object' && name !== null ? name : { type: 'env', name: String(name || '') }
38
+ }
39
+
40
+ export function resolveApiKey(apiKeyEnv, env = process.env) {
41
+ const name = String(apiKeyEnv || DEFAULT_API_KEY_ENV).trim() || DEFAULT_API_KEY_ENV
42
+ return {
43
+ envName: name,
44
+ value: String(env[name] || ''),
45
+ }
46
+ }
47
+
48
+ export async function saveCredentialKey(ctx, apiKeyEnv, apiKey) {
49
+ const name = String(apiKeyEnv || DEFAULT_API_KEY_ENV).trim() || DEFAULT_API_KEY_ENV
50
+ const value = String(apiKey || '').trim()
51
+
52
+ if (!value) {
53
+ throw new Error('API key cannot be empty')
54
+ }
55
+
56
+ const credentials = credentialsService(ctx)
57
+ if (!credentials || typeof credentials.set !== 'function') {
58
+ throw new Error('DSH credentials service is unavailable in this runtime profile')
59
+ }
60
+
61
+ const ref = await toCredentialRef(name)
62
+ await credentials.set(ref, value)
63
+ return { ok: true, envName: name }
64
+ }
65
+
66
+ export async function deleteCredentialKey(ctx, apiKeyEnv) {
67
+ const name = String(apiKeyEnv || '').trim()
68
+ if (!name) return { ok: false }
69
+ const credentials = credentialsService(ctx)
70
+ if (!credentials) return { ok: false }
71
+ try {
72
+ const ref = await toCredentialRef(name)
73
+ if (typeof credentials.unset === 'function') {
74
+ await credentials.unset(ref)
75
+ return { ok: true, envName: name }
76
+ }
77
+ } catch (err) {
78
+ ctx?.logger?.warn?.('[dsh-clinebot] Failed unsetting credential: ' + (err?.message || err))
79
+ }
80
+ return { ok: false }
81
+ }
82
+
83
+ export async function resolveKeyValue(ctx, apiKeyEnv) {
84
+ const refName = String(apiKeyEnv || DEFAULT_API_KEY_ENV).trim() || DEFAULT_API_KEY_ENV
85
+ const creds = credentialsService(ctx)
86
+ if (creds && typeof creds.resolve === 'function') {
87
+ try {
88
+ const ref = await toCredentialRef(refName)
89
+ const hit = await creds.resolve(ref)
90
+ if (hit?.value) {
91
+ return { envName: refName, value: hit.value, source: 'credentials' }
92
+ }
93
+ } catch {
94
+ /* miss */
95
+ }
96
+ }
97
+
98
+ const fromEnv = resolveApiKey(refName)
99
+ if (fromEnv.value) {
100
+ return { ...fromEnv, source: 'env' }
101
+ }
102
+
103
+ return { envName: refName, value: '', source: 'none' }
104
+ }