updated & tested 1pass

This commit is contained in:
waleed
2026-02-09 16:08:59 -08:00
parent 07719096ba
commit 0e8a06b906
9 changed files with 50 additions and 36 deletions

View File

@@ -254,7 +254,7 @@ Resolve a secret reference (op://vault/item/field) to its value. Service Account
| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `secret` | string | The resolved secret value |
| `value` | string | The resolved secret value |
| `reference` | string | The original secret reference URI |

View File

@@ -54,7 +54,7 @@ export async function POST(request: NextRequest) {
const parsedFields = params.fields
? (JSON.parse(params.fields) as Array<Record<string, any>>).map((f) => ({
id: f.id || '',
id: f.id || randomUUID().slice(0, 8),
title: f.label || f.title || '',
fieldType: toSdkFieldType(f.type || 'STRING'),
value: f.value || '',

View File

@@ -46,37 +46,41 @@ export async function POST(request: NextRequest) {
if (creds.mode === 'service_account') {
const client = await createOnePasswordClient(creds.serviceAccountToken!)
const existing = await client.items.get(params.vaultId, params.itemId)
const sdkItem = {
...existing,
id: params.itemId,
title: itemData.title || '',
category: toSdkCategory(itemData.category || 'LOGIN'),
title: itemData.title || existing.title,
category: itemData.category ? toSdkCategory(itemData.category) : existing.category,
vaultId: params.vaultId,
fields: (itemData.fields ?? []).map((f: Record<string, any>) => ({
id: f.id || '',
title: f.label || f.title || '',
fieldType: toSdkFieldType(f.type || 'STRING'),
value: f.value || '',
sectionId: f.section?.id ?? f.sectionId,
})),
sections: (itemData.sections ?? []).map((s: Record<string, any>) => ({
id: s.id || '',
title: s.label || s.title || '',
})),
notes: itemData.notes || '',
tags: itemData.tags ?? [],
websites: (itemData.urls ?? itemData.websites ?? []).map((u: Record<string, any>) => ({
url: u.href || u.url || '',
label: u.label || '',
autofillBehavior: 'AnywhereOnWebsite' as const,
})),
version: itemData.version ?? 0,
files: [],
createdAt: new Date(),
updatedAt: new Date(),
fields: itemData.fields
? (itemData.fields as Array<Record<string, any>>).map((f) => ({
id: f.id || randomUUID().slice(0, 8),
title: f.label || f.title || '',
fieldType: toSdkFieldType(f.type || 'STRING'),
value: f.value || '',
sectionId: f.section?.id ?? f.sectionId,
}))
: existing.fields,
sections: itemData.sections
? (itemData.sections as Array<Record<string, any>>).map((s) => ({
id: s.id || '',
title: s.label || s.title || '',
}))
: existing.sections,
notes: itemData.notes ?? existing.notes,
tags: itemData.tags ?? existing.tags,
websites:
itemData.urls || itemData.websites
? (itemData.urls ?? itemData.websites ?? []).map((u: Record<string, any>) => ({
url: u.href || u.url || '',
label: u.label || '',
autofillBehavior: 'AnywhereOnWebsite' as const,
}))
: existing.websites,
}
// Cast to any because toSdkCategory/toSdkFieldType return string literals
// that match SDK enum values but TypeScript can't verify this at compile time
const result = await client.items.put(sdkItem as any)
return NextResponse.json(normalizeSdkItem(result))
}

View File

@@ -42,7 +42,7 @@ export async function POST(request: NextRequest) {
const secret = await client.secrets.resolve(params.secretReference)
return NextResponse.json({
secret,
value: secret,
reference: params.secretReference,
})
} catch (error) {

View File

@@ -71,7 +71,7 @@ export const OnePasswordBlock: BlockConfig = {
id: 'secretReference',
title: 'Secret Reference',
type: 'short-input',
placeholder: 'op://vault-name/item-name/field-name',
placeholder: 'op://vault-name-or-id/item-name-or-id/field-name',
required: { field: 'operation', value: 'resolve_secret' },
condition: { field: 'operation', value: 'resolve_secret' },
},
@@ -80,6 +80,7 @@ export const OnePasswordBlock: BlockConfig = {
title: 'Vault ID',
type: 'short-input',
placeholder: 'Enter vault UUID',
password: true,
required: {
field: 'operation',
value: [
@@ -154,7 +155,7 @@ export const OnePasswordBlock: BlockConfig = {
},
{
id: 'fields',
title: 'Fields (JSON)',
title: 'Fields',
type: 'code',
placeholder:
'[\n {\n "label": "username",\n "value": "admin",\n "type": "STRING",\n "purpose": "USERNAME"\n }\n]',

View File

@@ -43,4 +43,13 @@ describe('isLikelyReferenceSegment', () => {
it('should return false when leading content is not comparator characters', () => {
expect(isLikelyReferenceSegment('<foo<bar>')).toBe(false)
})
it('should return true for references starting with a digit', () => {
expect(isLikelyReferenceSegment('<1password1>')).toBe(true)
expect(isLikelyReferenceSegment('<1password1.secret>')).toBe(true)
})
it('should return false for purely numeric references', () => {
expect(isLikelyReferenceSegment('<123>')).toBe(false)
})
})

View File

@@ -70,7 +70,7 @@ export function isLikelyReferenceSegment(segment: string): boolean {
if (INVALID_REFERENCE_CHARS.test(beforeDot) || INVALID_REFERENCE_CHARS.test(afterDot)) {
return false
}
} else if (INVALID_REFERENCE_CHARS.test(inner) || inner.match(/^\d/) || inner.match(/\s\d/)) {
} else if (INVALID_REFERENCE_CHARS.test(inner) || inner.match(/^\d+$/) || inner.match(/\s\d/)) {
return false
}

View File

@@ -49,19 +49,19 @@ export const resolveSecretTool: ToolConfig<
transformResponse: async (response) => {
const data = await response.json()
if (data.error) {
return { success: false, output: { secret: '', reference: '' }, error: data.error }
return { success: false, output: { value: '', reference: '' }, error: data.error }
}
return {
success: true,
output: {
secret: data.secret ?? '',
value: data.value ?? '',
reference: data.reference ?? '',
},
}
},
outputs: {
secret: { type: 'string', description: 'The resolved secret value' },
value: { type: 'string', description: 'The resolved secret value' },
reference: { type: 'string', description: 'The original secret reference URI' },
},
}

View File

@@ -153,7 +153,7 @@ export interface OnePasswordDeleteItemResponse extends ToolResponse {
export interface OnePasswordResolveSecretResponse extends ToolResponse {
output: {
secret: string
value: string
reference: string
}
}