mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-09 22:25:33 -05:00
update 1password to support cloud & locally hosted
This commit is contained in:
@@ -33,21 +33,21 @@ export function AgentIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M15.6667 9.25H4.66667C2.64162 9.25 1 10.8916 1 12.9167V18.4167C1 20.4417 2.64162 22.0833 4.66667 22.0833H15.6667C17.6917 22.0833 19.3333 20.4417 19.3333 18.4167V12.9167C19.3333 10.8916 17.6917 9.25 15.6667 9.25Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M10.1663 5.58464C11.1789 5.58464 11.9997 4.76382 11.9997 3.7513C11.9997 2.73878 11.1789 1.91797 10.1663 1.91797C9.15382 1.91797 8.33301 2.73878 8.33301 3.7513C8.33301 4.76382 9.15382 5.58464 10.1663 5.58464Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M10.167 5.58594V9.2526M7.41699 16.5859V14.7526M12.917 14.7526V16.5859'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -68,7 +68,7 @@ export function ApiIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M5.61111 24.3889C8.5 27.2778 12.4722 25.4722 13.5556 24.3889L15.7222 22.2222L7.77778 14.2778L5.61111 16.4444C4.52778 17.5278 2.72222 21.5 5.61111 24.3889ZM5.61111 24.3889L2 28M24.3889 5.61111C21.5 2.72222 17.5278 4.52778 16.4444 5.61111L14.2778 7.77778L22.2222 15.7222L24.3889 13.5556C25.4722 12.4722 27.2778 8.5 24.3889 5.61111ZM24.3889 5.61111L28 2M15.7222 9.22222L12.8333 12.1111M20.7778 14.2778L17.8889 17.1667'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -90,7 +90,7 @@ export function ConditionalIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<path
|
||||
d='M23.1015 1.01616C22.1825 1.01442 21.2926 1.33795 20.5894 1.92946C19.8861 2.52098 19.4149 3.34229 19.2592 4.24794C19.1035 5.15358 19.2733 6.08512 19.7386 6.87755C20.2039 7.66998 20.9346 8.27217 21.8014 8.57745V12.7169H6.20035V8.57745C7.06779 8.27077 7.79888 7.6673 8.26441 6.87372C8.72994 6.08013 8.89994 5.14752 8.74435 4.24072C8.58877 3.33391 8.11762 2.5113 7.41419 1.91828C6.71075 1.32526 5.82032 1 4.90027 1C3.98021 1 3.08978 1.32526 2.38634 1.91828C1.68291 2.5113 1.21176 3.33391 1.05618 4.24072C0.900594 5.14752 1.07059 6.08013 1.53612 6.87372C2.00165 7.6673 2.73274 8.27077 3.60018 8.57745V12.7169C3.60018 13.4065 3.87413 14.0679 4.36175 14.5555C4.84938 15.0432 5.51074 15.3171 6.20035 15.3171H12.7008V20.7567C11.8333 21.0633 11.1023 21.6668 10.6367 22.4604C10.1712 23.254 10.0012 24.1866 10.1568 25.0934C10.3124 26.0002 10.7835 26.8228 11.4869 27.4158C12.1904 28.0089 13.0808 28.3341 14.0009 28.3341C14.9209 28.3341 15.8114 28.0089 16.5148 27.4158C17.2182 26.8228 17.6894 26.0002 17.845 25.0934C18.0005 24.1866 17.8305 23.254 17.365 22.4604C16.8995 21.6668 16.1684 21.0633 15.301 20.7567V15.3171H21.8014C22.491 15.3171 23.1524 15.0432 23.64 14.5555C24.1276 14.0679 24.4015 13.4065 24.4015 12.7169V8.57745C25.2683 8.27217 25.999 7.66998 26.4643 6.87755C26.9296 6.08512 27.0994 5.15358 26.9437 4.24794C26.788 3.34229 26.3168 2.52098 25.6135 1.92946C24.9103 1.33795 24.0204 1.01442 23.1015 1.01616ZM4.90027 6.2165C4.64313 6.2165 4.39177 6.14025 4.17798 5.99739C3.96418 5.85454 3.79754 5.65149 3.69914 5.41393C3.60074 5.17637 3.575 4.91497 3.62516 4.66278C3.67532 4.41059 3.79915 4.17893 3.98097 3.99711C4.16279 3.81529 4.39444 3.69147 4.64663 3.64131C4.89882 3.59114 5.16023 3.61689 5.39779 3.71529C5.63535 3.81369 5.83839 3.98033 5.98125 4.19412C6.1241 4.40792 6.20035 4.65928 6.20035 4.91641C6.20035 5.26122 6.06338 5.5919 5.81956 5.83571C5.57575 6.07953 5.24507 6.2165 4.90027 6.2165ZM14.0009 25.7178C13.7437 25.7178 13.4924 25.6415 13.2786 25.4987C13.0648 25.3558 12.8981 25.1528 12.7997 24.9152C12.7013 24.6777 12.6756 24.4163 12.7258 24.1641C12.7759 23.9119 12.8997 23.6802 13.0816 23.4984C13.2634 23.3166 13.495 23.1928 13.7472 23.1426C13.9994 23.0924 14.2608 23.1182 14.4984 23.2166C14.7359 23.315 14.939 23.4816 15.0818 23.6954C15.2247 23.9092 15.301 24.1606 15.301 24.4177C15.301 24.7625 15.164 25.0932 14.9202 25.337C14.6764 25.5808 14.3457 25.7178 14.0009 25.7178ZM23.1015 6.2165C22.8443 6.2165 22.593 6.14025 22.3792 5.99739C22.1654 5.85454 21.9987 5.65149 21.9003 5.41393C21.8019 5.17637 21.7762 4.91497 21.8264 4.66278C21.8765 4.41059 22.0003 4.17893 22.1822 3.99711C22.364 3.81529 22.5956 3.69147 22.8478 3.64131C23.1 3.59114 23.3614 3.61689 23.599 3.71529C23.8365 3.81369 24.0396 3.98033 24.1824 4.19412C24.3253 4.40792 24.4015 4.65928 24.4015 4.91641C24.4015 5.26122 24.2646 5.5919 24.0208 5.83571C23.777 6.07953 23.4463 6.2165 23.1015 6.2165Z'
|
||||
fill='currentColor'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='0.25'
|
||||
/>
|
||||
</svg>
|
||||
@@ -113,7 +113,7 @@ export function NoteIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='16'
|
||||
height='18'
|
||||
rx='2.5'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
fill='none'
|
||||
/>
|
||||
@@ -139,7 +139,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
cx='12'
|
||||
cy='6'
|
||||
r='3'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -151,7 +151,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='8'
|
||||
x='2'
|
||||
y='16'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -163,7 +163,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='8'
|
||||
x='14'
|
||||
y='16'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -171,7 +171,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<path
|
||||
className='a'
|
||||
d='M6,16V14a2,2,0,0,1,2-2h8a2,2,0,0,1,2,2v2'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -182,7 +182,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
x2='12'
|
||||
y1='9'
|
||||
y2='12'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -203,7 +203,7 @@ export function SignalIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M23.964 33.2C26.252 28.416 27.5 23.216 27.5 17.6C27.5 11.984 26.252 6.576 23.964 2M16.476 29.664C18.14 25.92 19.18 21.76 19.18 17.6C19.18 13.44 18.14 9.072 16.476 5.328M8.988 26.128C10.236 23.424 10.86 20.512 10.86 17.6C10.86 14.688 10.236 11.568 8.988 9.072M1.5 22.384C2.124 20.928 2.54 19.264 2.54 17.6C2.54 15.936 2.124 14.064 1.5 12.608'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -224,7 +224,7 @@ export function CalendarIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M21.5 4.88889V2M8.5 4.88889V2M2.36111 9.22222H27.6389M2 12.1747C2 9.11967 2 7.59144 2.62978 6.42433C3.19924 5.38333 4.08288 4.54873 5.15467 4.03956C6.39111 3.44444 8.00889 3.44444 11.2444 3.44444H18.7556C21.9911 3.44444 23.6089 3.44444 24.8453 4.03956C25.933 4.56244 26.8156 5.39733 27.3702 6.42289C28 7.59289 28 9.12111 28 12.1761V19.2712C28 22.3262 28 23.8544 27.3702 25.0216C26.8008 26.0626 25.9171 26.8972 24.8453 27.4063C23.6089 28 21.9911 28 18.7556 28H11.2444C8.00889 28 6.39111 28 5.15467 27.4049C4.0831 26.8961 3.19948 26.062 2.62978 25.0216C2 23.8516 2 22.3233 2 19.2683V12.1747Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -245,7 +245,7 @@ export function MessagesIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M4.88867 14.999C6.27936 13.956 7.99961 13.4496 9.7336 13.5728C11.4676 13.6961 13.0989 14.4406 14.3281 15.6698C15.5574 16.899 16.3019 18.5304 16.4252 20.2644C16.5484 21.9984 16.042 23.7186 14.999 25.1093M4.88867 14.999C3.99176 15.6717 3.2638 16.5439 2.76241 17.5467C2.26103 18.5495 2 19.6552 2 20.7763C1.99954 21.5025 2.10861 22.2246 2.32353 22.9183C2.71639 24.1893 2.4333 25.6047 2.18054 26.9393C2.15813 27.0534 2.16551 27.1713 2.20198 27.2817C2.23845 27.392 2.30278 27.4912 2.38874 27.5694C2.4747 27.6477 2.57939 27.7025 2.6927 27.7285C2.80601 27.7544 2.92411 27.7508 3.03559 27.7178C4.26038 27.3827 5.47795 27.0967 6.72875 27.556C7.52721 27.849 8.37115 27.9986 9.22166 27.998C10.343 27.9991 11.4491 27.7386 12.4521 27.2371C13.455 26.7356 14.3271 26.0071 14.999 25.1093M4.88867 14.999C4.88867 8.23229 9.04112 2 16.4433 2C18.2963 1.99968 20.1222 2.44502 21.767 3.29845C23.4118 4.15189 24.8272 5.38838 25.8938 6.90363C26.9605 8.41888 27.647 10.1684 27.8956 12.0047C28.1441 13.841 27.9474 15.7101 27.322 17.4544C26.6345 19.3695 27.3755 21.9347 27.8088 24.0521C27.834 24.1648 27.8288 24.2822 27.7937 24.3923C27.7587 24.5024 27.6949 24.6011 27.6091 24.6785C27.5232 24.7558 27.4184 24.8089 27.3052 24.8323C27.1921 24.8557 27.0748 24.8486 26.9653 24.8118C25.0703 24.2196 22.846 23.3877 21.0652 24.1387C19.1384 24.9504 17.1135 25.1093 14.999 25.1093'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -266,7 +266,7 @@ export function NotificationsIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M19.9056 24.7496H10.0908M19.9056 24.7496H25.7783C28.8267 24.7496 28.3116 21.7272 26.7695 20.1932C21.2153 14.6764 29.1046 2 14.9982 2C0.891783 2 8.78265 14.6748 3.22849 20.1932C1.74489 21.6687 1.11278 24.7496 4.21973 24.7496H10.0908M19.9056 24.7496C19.9056 27.8777 18.8526 31.2495 14.9982 31.2495C11.1437 31.2495 10.0908 27.8777 10.0908 24.7496'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -287,7 +287,7 @@ export function MailIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M2.35742 5.83288L11.7674 12.1071C13.0656 12.9712 13.7141 13.404 14.4151 13.5725C15.0352 13.7208 15.681 13.7208 16.2998 13.5725C17.0008 13.404 17.6492 12.9712 18.9475 12.1071L28.3574 5.83288M8.82844 21.7219H21.8864C24.1513 21.7219 25.2837 21.7219 26.1492 21.2811C26.9097 20.8931 27.5278 20.2744 27.9152 19.5137C28.3574 18.6482 28.3574 17.5158 28.3574 15.2509V7.97102C28.3574 5.70616 28.3574 4.57373 27.9166 3.70823C27.5288 2.94727 26.9102 2.32858 26.1492 1.94084C25.2837 1.5 24.1513 1.5 21.8864 1.5H8.82844C6.56358 1.5 5.43115 1.5 4.56566 1.94084C3.80519 2.32881 3.187 2.94747 2.79961 3.70823C2.35742 4.57373 2.35742 5.70616 2.35742 7.97102V15.2509C2.35742 17.5158 2.35742 18.6482 2.79826 19.5137C3.186 20.2747 3.80469 20.8933 4.56566 21.2811C5.43115 21.7219 6.56358 21.7219 8.82844 21.7219Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -312,25 +312,33 @@ export function MailServerIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='18'
|
||||
height='16'
|
||||
rx='2'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M3 8L10.89 13.26C11.2187 13.4793 11.6049 13.5963 12 13.5963C12.3951 13.5963 12.7813 13.4793 13.11 13.26L21 8'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<line x1='7' y1='16' x2='7' y2='16' stroke='#000000' strokeWidth='2' strokeLinecap='round' />
|
||||
<line
|
||||
x1='7'
|
||||
y1='16'
|
||||
x2='7'
|
||||
y2='16'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
/>
|
||||
<line
|
||||
x1='10'
|
||||
y1='16'
|
||||
x2='10'
|
||||
y2='16'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
/>
|
||||
@@ -350,7 +358,7 @@ export function CodeIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M23.2639 6.83064L23.6375 7.20422C26.5433 10.1117 27.9971 11.5638 27.9971 13.37C27.9971 15.1762 26.5433 16.63 23.6375 19.5358L23.2639 19.9094M18.0434 2L11.9507 24.7401M6.72863 6.83064L6.35504 7.20422C3.45081 10.1117 1.99707 11.5638 1.99707 13.37C1.99707 15.1762 3.45081 16.63 6.35829 19.5358L6.73187 19.9094'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.6'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -837,7 +845,7 @@ export function xIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<path
|
||||
d='M 5.9199219 6 L 20.582031 27.375 L 6.2304688 44 L 9.4101562 44 L 21.986328 29.421875 L 31.986328 44 L 44 44 L 28.681641 21.669922 L 42.199219 6 L 39.029297 6 L 27.275391 19.617188 L 17.933594 6 L 5.9199219 6 z M 9.7167969 8 L 16.880859 8 L 40.203125 42 L 33.039062 42 L 9.7167969 8 z'
|
||||
fill='currentColor'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='0.5'
|
||||
/>
|
||||
</svg>
|
||||
@@ -1491,14 +1499,14 @@ export function DocumentIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M8 15.2H15.2M8 20H11.6M2 4.4V23.6C2 24.2365 2.25286 24.847 2.70294 25.2971C3.15303 25.7471 3.76348 26 4.4 26H18.8C19.4365 26 20.047 25.7471 20.4971 25.2971C20.9471 24.847 21.2 24.2365 21.2 23.6V9.6104C21.2 9.29067 21.136 8.97417 21.012 8.67949C20.8879 8.38481 20.7062 8.11789 20.4776 7.8944L15.1496 2.684C14.7012 2.24559 14.0991 2.00008 13.472 2H4.4C3.76348 2 3.15303 2.25286 2.70294 2.70294C2.25286 3.15303 2 3.76348 2 4.4Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.25'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M14 2V6.8C14 7.43652 14.2529 8.04697 14.7029 8.49706C15.153 8.94714 15.7635 9.2 16.4 9.2H21.2'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.25'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
@@ -3993,7 +4001,7 @@ export function SmtpIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M2.35742 5.83288L11.7674 12.1071C13.0656 12.9712 13.7141 13.404 14.4151 13.5725C15.0352 13.7208 15.681 13.7208 16.2998 13.5725C17.0008 13.404 17.6492 12.9712 18.9475 12.1071L28.3574 5.83288M8.82844 21.7219H21.8864C24.1513 21.7219 25.2837 21.7219 26.1492 21.2811C26.9097 20.8931 27.5278 20.2744 27.9152 19.5137C28.3574 18.6482 28.3574 17.5158 28.3574 15.2509V7.97102C28.3574 5.70616 28.3574 4.57373 27.9166 3.70823C27.5288 2.94727 26.9102 2.32858 26.1492 1.94084C25.2837 1.5 24.1513 1.5 21.8864 1.5H8.82844C6.56358 1.5 5.43115 1.5 4.56566 1.94084C3.80519 2.32881 3.187 2.94747 2.79961 3.70823C2.35742 4.57373 2.35742 5.70616 2.35742 7.97102V15.2509C2.35742 17.5158 2.35742 18.6482 2.79826 19.5137C3.186 20.2747 3.80469 20.8933 4.56566 21.2811C5.43115 21.7219 6.56358 21.7219 8.82844 21.7219Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -4219,7 +4227,7 @@ export function A2AIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<circle cx='316' cy='307' r='27' fill='currentColor' />
|
||||
<path
|
||||
d='M336.5 191.003H162C97.6588 191.003 45.5 243.162 45.5 307.503C45.5 371.844 97.6442 424.003 161.985 424.003C206.551 424.003 256.288 424.003 296.5 424.003C487.5 424.003 374 191.005 569 191.001C613.886 191 658.966 191 698.025 191C762.366 191.001 814.5 243.16 814.5 307.501C814.5 371.843 762.34 424.003 697.998 424.003H523.5'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='48'
|
||||
strokeLinecap='round'
|
||||
/>
|
||||
@@ -4489,14 +4497,14 @@ export function RssIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M4 11C6.38695 11 8.67613 11.9482 10.364 13.636C12.0518 15.3239 13 17.6131 13 20'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M4 4C8.24346 4 12.3131 5.68571 15.3137 8.68629C18.3143 11.6869 20 15.7565 20 20'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
|
||||
@@ -313,45 +313,7 @@ Retrieve multiple Jira issues from a project in bulk
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `total` | number | Total number of issues in the project |
|
||||
| `issues` | array | Array of Jira issues |
|
||||
| ↳ `id` | string | Issue ID |
|
||||
| ↳ `key` | string | Issue key \(e.g., PROJ-123\) |
|
||||
| ↳ `self` | string | REST API URL for this issue |
|
||||
| ↳ `summary` | string | Issue summary |
|
||||
| ↳ `description` | string | Issue description text |
|
||||
| ↳ `status` | object | Issue status |
|
||||
| ↳ `id` | string | Status ID |
|
||||
| ↳ `name` | string | Status name |
|
||||
| ↳ `issuetype` | object | Issue type |
|
||||
| ↳ `id` | string | Issue type ID |
|
||||
| ↳ `name` | string | Issue type name |
|
||||
| ↳ `priority` | object | Issue priority |
|
||||
| ↳ `id` | string | Priority ID |
|
||||
| ↳ `name` | string | Priority name |
|
||||
| ↳ `assignee` | object | Assigned user |
|
||||
| ↳ `accountId` | string | Atlassian account ID |
|
||||
| ↳ `displayName` | string | Display name |
|
||||
| ↳ `created` | string | ISO 8601 creation timestamp |
|
||||
| ↳ `updated` | string | ISO 8601 last updated timestamp |
|
||||
|
||||
### `jira_bulk_read`
|
||||
|
||||
Retrieve multiple Jira issues from a project in bulk with cursor-based pagination (V2 - uses nextPageToken)
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Jira domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `projectId` | string | Yes | Jira project key \(e.g., PROJ\) |
|
||||
| `cloudId` | string | No | Jira Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `total` | number | Total number of issues in the project \(may not always be available\) |
|
||||
| `issues` | array | Array of Jira issues |
|
||||
| ↳ `id` | string | Issue ID |
|
||||
| ↳ `key` | string | Issue key \(e.g., PROJ-123\) |
|
||||
@@ -374,7 +336,6 @@ Retrieve multiple Jira issues from a project in bulk with cursor-based paginatio
|
||||
| ↳ `updated` | string | ISO 8601 last updated timestamp |
|
||||
| `nextPageToken` | string | Cursor token for the next page. Null when no more results. |
|
||||
| `isLast` | boolean | Whether this is the last page of results |
|
||||
| `total` | number | Total number of issues in the project \(may not always be available\) |
|
||||
|
||||
### `jira_delete_issue`
|
||||
|
||||
@@ -454,90 +415,8 @@ Search for Jira issues using JQL (Jira Query Language)
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Jira domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `jql` | string | Yes | JQL query string to search for issues \(e.g., "project = PROJ AND status = Open"\) |
|
||||
| `startAt` | number | No | The index of the first result to return \(for pagination\) |
|
||||
| `maxResults` | number | No | Maximum number of results to return \(default: 50\) |
|
||||
| `fields` | array | No | Array of field names to return \(default: all navigable\). Use "*all" for every field. |
|
||||
| `cloudId` | string | No | Jira Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `ts` | string | ISO 8601 timestamp of the operation |
|
||||
| `total` | number | Total number of matching issues |
|
||||
| `startAt` | number | Pagination start index |
|
||||
| `maxResults` | number | Maximum results per page |
|
||||
| `issues` | array | Array of matching issues |
|
||||
| ↳ `id` | string | Issue ID |
|
||||
| ↳ `key` | string | Issue key \(e.g., PROJ-123\) |
|
||||
| ↳ `self` | string | REST API URL for this issue |
|
||||
| ↳ `summary` | string | Issue summary |
|
||||
| ↳ `description` | string | Issue description text \(extracted from ADF\) |
|
||||
| ↳ `status` | object | Issue status |
|
||||
| ↳ `id` | string | Status ID |
|
||||
| ↳ `name` | string | Status name \(e.g., Open, In Progress, Done\) |
|
||||
| ↳ `description` | string | Status description |
|
||||
| ↳ `statusCategory` | object | Status category grouping |
|
||||
| ↳ `id` | number | Status category ID |
|
||||
| ↳ `key` | string | Status category key \(e.g., new, indeterminate, done\) |
|
||||
| ↳ `name` | string | Status category name \(e.g., To Do, In Progress, Done\) |
|
||||
| ↳ `colorName` | string | Status category color \(e.g., blue-gray, yellow, green\) |
|
||||
| ↳ `issuetype` | object | Issue type |
|
||||
| ↳ `id` | string | Issue type ID |
|
||||
| ↳ `name` | string | Issue type name \(e.g., Task, Bug, Story, Epic\) |
|
||||
| ↳ `description` | string | Issue type description |
|
||||
| ↳ `subtask` | boolean | Whether this is a subtask type |
|
||||
| ↳ `iconUrl` | string | URL to the issue type icon |
|
||||
| ↳ `project` | object | Project the issue belongs to |
|
||||
| ↳ `id` | string | Project ID |
|
||||
| ↳ `key` | string | Project key \(e.g., PROJ\) |
|
||||
| ↳ `name` | string | Project name |
|
||||
| ↳ `projectTypeKey` | string | Project type key \(e.g., software, business\) |
|
||||
| ↳ `priority` | object | Issue priority |
|
||||
| ↳ `id` | string | Priority ID |
|
||||
| ↳ `name` | string | Priority name \(e.g., Highest, High, Medium, Low, Lowest\) |
|
||||
| ↳ `iconUrl` | string | URL to the priority icon |
|
||||
| ↳ `assignee` | object | Assigned user |
|
||||
| ↳ `accountId` | string | Atlassian account ID of the user |
|
||||
| ↳ `displayName` | string | Display name of the user |
|
||||
| ↳ `active` | boolean | Whether the user account is active |
|
||||
| ↳ `emailAddress` | string | Email address of the user |
|
||||
| ↳ `accountType` | string | Type of account \(e.g., atlassian, app, customer\) |
|
||||
| ↳ `avatarUrl` | string | URL to the user avatar \(48x48\) |
|
||||
| ↳ `timeZone` | string | User timezone |
|
||||
| ↳ `reporter` | object | Reporter user |
|
||||
| ↳ `accountId` | string | Atlassian account ID of the user |
|
||||
| ↳ `displayName` | string | Display name of the user |
|
||||
| ↳ `active` | boolean | Whether the user account is active |
|
||||
| ↳ `emailAddress` | string | Email address of the user |
|
||||
| ↳ `accountType` | string | Type of account \(e.g., atlassian, app, customer\) |
|
||||
| ↳ `avatarUrl` | string | URL to the user avatar \(48x48\) |
|
||||
| ↳ `timeZone` | string | User timezone |
|
||||
| ↳ `labels` | array | Issue labels |
|
||||
| ↳ `components` | array | Issue components |
|
||||
| ↳ `id` | string | Component ID |
|
||||
| ↳ `name` | string | Component name |
|
||||
| ↳ `description` | string | Component description |
|
||||
| ↳ `resolution` | object | Issue resolution |
|
||||
| ↳ `id` | string | Resolution ID |
|
||||
| ↳ `name` | string | Resolution name \(e.g., Fixed, Duplicate, Won't Fix\) |
|
||||
| ↳ `description` | string | Resolution description |
|
||||
| ↳ `duedate` | string | Due date \(YYYY-MM-DD\) |
|
||||
| ↳ `created` | string | ISO 8601 timestamp when the issue was created |
|
||||
| ↳ `updated` | string | ISO 8601 timestamp when the issue was last updated |
|
||||
|
||||
### `jira_search_issues`
|
||||
|
||||
Search for Jira issues using JQL with cursor-based pagination (V2 - uses nextPageToken)
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `domain` | string | Yes | Your Jira domain \(e.g., yourcompany.atlassian.net\) |
|
||||
| `jql` | string | Yes | JQL query string to search for issues \(e.g., "project = PROJ AND status = Open"\) |
|
||||
| `startAt` | number | No | The index of the first result to return \(for pagination\) |
|
||||
| `maxResults` | number | No | Maximum number of results to return \(default: 50\) |
|
||||
| `nextPageToken` | string | No | Cursor token for the next page of results. Omit for the first page. |
|
||||
| `maxResults` | number | No | Maximum number of results to return per page \(default: 50\) |
|
||||
| `fields` | array | No | Array of field names to return \(default: all navigable\). Use "*all" for every field. |
|
||||
| `cloudId` | string | No | Jira Cloud ID for the instance. If not provided, it will be fetched using the domain. |
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ By connecting Sim with 1Password, you empower your agents to securely manage sec
|
||||
|
||||
## Usage Instructions
|
||||
|
||||
Access and manage secrets stored in 1Password vaults using the Connect API. List vaults, retrieve items with their fields and secrets, create new items, update existing ones, and delete items.
|
||||
Access and manage secrets stored in 1Password vaults using the Connect API or Service Account SDK. List vaults, retrieve items with their fields and secrets, create new items, update existing ones, delete items, and resolve secret references.
|
||||
|
||||
|
||||
|
||||
@@ -37,14 +37,16 @@ Access and manage secrets stored in 1Password vaults using the Connect API. List
|
||||
|
||||
### `onepassword_list_vaults`
|
||||
|
||||
List all vaults accessible by the Connect token
|
||||
List all vaults accessible by the Connect token or Service Account
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `filter` | string | No | SCIM filter expression \(e.g., name eq "My Vault"\) |
|
||||
|
||||
#### Output
|
||||
@@ -69,8 +71,10 @@ Get details of a specific vault by ID
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `vaultId` | string | Yes | The vault UUID |
|
||||
|
||||
#### Output
|
||||
@@ -95,8 +99,10 @@ List items in a vault. Returns summaries without field values.
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `vaultId` | string | Yes | The vault UUID to list items from |
|
||||
| `filter` | string | No | SCIM filter expression \(e.g., title eq "API Key" or tag eq "production"\) |
|
||||
|
||||
@@ -130,8 +136,10 @@ Get full details of an item including all fields and secrets
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `vaultId` | string | Yes | The vault UUID |
|
||||
| `itemId` | string | Yes | The item UUID to retrieve |
|
||||
|
||||
@@ -149,8 +157,10 @@ Create a new item in a vault
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `vaultId` | string | Yes | The vault UUID to create the item in |
|
||||
| `category` | string | Yes | Item category \(e.g., LOGIN, PASSWORD, API_CREDENTIAL, SECURE_NOTE, SERVER, DATABASE\) |
|
||||
| `title` | string | No | Item title |
|
||||
@@ -171,8 +181,10 @@ Replace an entire item with new data (full update)
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `vaultId` | string | Yes | The vault UUID |
|
||||
| `itemId` | string | Yes | The item UUID to replace |
|
||||
| `item` | string | Yes | JSON object representing the full item \(e.g., \{"vault":\{"id":"..."\},"category":"LOGIN","title":"My Item","fields":\[...\]\}\) |
|
||||
@@ -191,8 +203,10 @@ Update an existing item using JSON Patch operations (RFC6902)
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `vaultId` | string | Yes | The vault UUID |
|
||||
| `itemId` | string | Yes | The item UUID to update |
|
||||
| `operations` | string | Yes | JSON array of RFC6902 patch operations \(e.g., \[\{"op":"replace","path":"/title","value":"New Title"\}\]\) |
|
||||
@@ -211,8 +225,10 @@ Delete an item from a vault
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `apiKey` | string | Yes | 1Password Connect API token |
|
||||
| `serverUrl` | string | Yes | 1Password Connect server URL \(e.g., http://localhost:8080\) |
|
||||
| `connectionMode` | string | No | Connection mode: "service_account" or "connect" |
|
||||
| `serviceAccountToken` | string | No | 1Password Service Account token \(for Service Account mode\) |
|
||||
| `apiKey` | string | No | 1Password Connect API token \(for Connect Server mode\) |
|
||||
| `serverUrl` | string | No | 1Password Connect server URL \(for Connect Server mode\) |
|
||||
| `vaultId` | string | Yes | The vault UUID |
|
||||
| `itemId` | string | Yes | The item UUID to delete |
|
||||
|
||||
@@ -222,4 +238,23 @@ Delete an item from a vault
|
||||
| --------- | ---- | ----------- |
|
||||
| `success` | boolean | Whether the item was successfully deleted |
|
||||
|
||||
### `onepassword_resolve_secret`
|
||||
|
||||
Resolve a secret reference (op://vault/item/field) to its value. Service Account mode only.
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `connectionMode` | string | No | Connection mode: must be "service_account" for this operation |
|
||||
| `serviceAccountToken` | string | Yes | 1Password Service Account token |
|
||||
| `secretReference` | string | Yes | Secret reference URI \(e.g., op://vault-name/item-name/field-name or op://vault-name/item-name/section-name/field-name\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `secret` | string | The resolved secret value |
|
||||
| `reference` | string | The original secret reference URI |
|
||||
|
||||
|
||||
|
||||
114
apps/sim/app/api/tools/onepassword/create-item/route.ts
Normal file
114
apps/sim/app/api/tools/onepassword/create-item/route.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
normalizeSdkItem,
|
||||
resolveCredentials,
|
||||
toSdkCategory,
|
||||
toSdkFieldType,
|
||||
} from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordCreateItemAPI')
|
||||
|
||||
const CreateItemSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
vaultId: z.string().min(1, 'Vault ID is required'),
|
||||
category: z.string().min(1, 'Category is required'),
|
||||
title: z.string().nullish(),
|
||||
tags: z.string().nullish(),
|
||||
fields: z.string().nullish(),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password create-item attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = CreateItemSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
|
||||
logger.info(`[${requestId}] Creating item in vault ${params.vaultId} (${creds.mode} mode)`)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
|
||||
const parsedTags = params.tags
|
||||
? params.tags
|
||||
.split(',')
|
||||
.map((t) => t.trim())
|
||||
.filter(Boolean)
|
||||
: undefined
|
||||
|
||||
const parsedFields = params.fields
|
||||
? (JSON.parse(params.fields) as Array<Record<string, any>>).map((f) => ({
|
||||
id: f.id || '',
|
||||
title: f.label || f.title || '',
|
||||
fieldType: toSdkFieldType(f.type || 'STRING'),
|
||||
value: f.value || '',
|
||||
sectionId: f.section?.id ?? f.sectionId,
|
||||
}))
|
||||
: undefined
|
||||
|
||||
// Cast to any because toSdkCategory/toSdkFieldType return string literals
|
||||
// that match SDK enum values but TypeScript can't verify this at compile time
|
||||
const item = await client.items.create({
|
||||
vaultId: params.vaultId,
|
||||
category: toSdkCategory(params.category) as any,
|
||||
title: params.title || '',
|
||||
tags: parsedTags,
|
||||
fields: parsedFields as any,
|
||||
})
|
||||
|
||||
return NextResponse.json(normalizeSdkItem(item))
|
||||
}
|
||||
|
||||
const connectBody: Record<string, unknown> = {
|
||||
vault: { id: params.vaultId },
|
||||
category: params.category,
|
||||
}
|
||||
if (params.title) connectBody.title = params.title
|
||||
if (params.tags) connectBody.tags = params.tags.split(',').map((t) => t.trim())
|
||||
if (params.fields) connectBody.fields = JSON.parse(params.fields)
|
||||
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: `/v1/vaults/${params.vaultId}/items`,
|
||||
method: 'POST',
|
||||
body: connectBody,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.message || 'Failed to create item' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] Create item failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to create item: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
70
apps/sim/app/api/tools/onepassword/delete-item/route.ts
Normal file
70
apps/sim/app/api/tools/onepassword/delete-item/route.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { connectRequest, createOnePasswordClient, resolveCredentials } from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordDeleteItemAPI')
|
||||
|
||||
const DeleteItemSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
vaultId: z.string().min(1, 'Vault ID is required'),
|
||||
itemId: z.string().min(1, 'Item ID is required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password delete-item attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = DeleteItemSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
|
||||
logger.info(
|
||||
`[${requestId}] Deleting item ${params.itemId} from vault ${params.vaultId} (${creds.mode} mode)`
|
||||
)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
await client.items.delete(params.vaultId, params.itemId)
|
||||
return NextResponse.json({ success: true })
|
||||
}
|
||||
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: `/v1/vaults/${params.vaultId}/items/${params.itemId}`,
|
||||
method: 'DELETE',
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json().catch(() => ({}))
|
||||
return NextResponse.json(
|
||||
{ error: (data as Record<string, string>).message || 'Failed to delete item' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] Delete item failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to delete item: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
75
apps/sim/app/api/tools/onepassword/get-item/route.ts
Normal file
75
apps/sim/app/api/tools/onepassword/get-item/route.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
normalizeSdkItem,
|
||||
resolveCredentials,
|
||||
} from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordGetItemAPI')
|
||||
|
||||
const GetItemSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
vaultId: z.string().min(1, 'Vault ID is required'),
|
||||
itemId: z.string().min(1, 'Item ID is required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password get-item attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = GetItemSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
|
||||
logger.info(
|
||||
`[${requestId}] Getting item ${params.itemId} from vault ${params.vaultId} (${creds.mode} mode)`
|
||||
)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
const item = await client.items.get(params.vaultId, params.itemId)
|
||||
return NextResponse.json(normalizeSdkItem(item))
|
||||
}
|
||||
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: `/v1/vaults/${params.vaultId}/items/${params.itemId}`,
|
||||
method: 'GET',
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.message || 'Failed to get item' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] Get item failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to get item: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
78
apps/sim/app/api/tools/onepassword/get-vault/route.ts
Normal file
78
apps/sim/app/api/tools/onepassword/get-vault/route.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
normalizeSdkVault,
|
||||
resolveCredentials,
|
||||
} from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordGetVaultAPI')
|
||||
|
||||
const GetVaultSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
vaultId: z.string().min(1, 'Vault ID is required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password get-vault attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = GetVaultSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
|
||||
logger.info(`[${requestId}] Getting 1Password vault ${params.vaultId} (${creds.mode} mode)`)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
const vaults = await client.vaults.list()
|
||||
const vault = vaults.find((v) => v.id === params.vaultId)
|
||||
|
||||
if (!vault) {
|
||||
return NextResponse.json({ error: 'Vault not found' }, { status: 404 })
|
||||
}
|
||||
|
||||
return NextResponse.json(normalizeSdkVault(vault))
|
||||
}
|
||||
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: `/v1/vaults/${params.vaultId}`,
|
||||
method: 'GET',
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.message || 'Failed to get vault' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] Get vault failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to get vault: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
87
apps/sim/app/api/tools/onepassword/list-items/route.ts
Normal file
87
apps/sim/app/api/tools/onepassword/list-items/route.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
normalizeSdkItemOverview,
|
||||
resolveCredentials,
|
||||
} from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordListItemsAPI')
|
||||
|
||||
const ListItemsSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
vaultId: z.string().min(1, 'Vault ID is required'),
|
||||
filter: z.string().nullish(),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password list-items attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = ListItemsSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
|
||||
logger.info(`[${requestId}] Listing items in vault ${params.vaultId} (${creds.mode} mode)`)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
const items = await client.items.list(params.vaultId)
|
||||
const normalized = items.map(normalizeSdkItemOverview)
|
||||
|
||||
if (params.filter) {
|
||||
const filterLower = params.filter.toLowerCase()
|
||||
const filtered = normalized.filter(
|
||||
(item) =>
|
||||
item.title?.toLowerCase().includes(filterLower) ||
|
||||
item.id?.toLowerCase().includes(filterLower)
|
||||
)
|
||||
return NextResponse.json(filtered)
|
||||
}
|
||||
|
||||
return NextResponse.json(normalized)
|
||||
}
|
||||
|
||||
const query = params.filter ? `filter=${encodeURIComponent(params.filter)}` : undefined
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: `/v1/vaults/${params.vaultId}/items`,
|
||||
method: 'GET',
|
||||
query,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.message || 'Failed to list items' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] List items failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to list items: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
85
apps/sim/app/api/tools/onepassword/list-vaults/route.ts
Normal file
85
apps/sim/app/api/tools/onepassword/list-vaults/route.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
normalizeSdkVault,
|
||||
resolveCredentials,
|
||||
} from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordListVaultsAPI')
|
||||
|
||||
const ListVaultsSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
filter: z.string().nullish(),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password list-vaults attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = ListVaultsSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
|
||||
logger.info(`[${requestId}] Listing 1Password vaults (${creds.mode} mode)`)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
const vaults = await client.vaults.list()
|
||||
const normalized = vaults.map(normalizeSdkVault)
|
||||
|
||||
if (params.filter) {
|
||||
const filterLower = params.filter.toLowerCase()
|
||||
const filtered = normalized.filter(
|
||||
(v) =>
|
||||
v.name?.toLowerCase().includes(filterLower) || v.id?.toLowerCase().includes(filterLower)
|
||||
)
|
||||
return NextResponse.json(filtered)
|
||||
}
|
||||
|
||||
return NextResponse.json(normalized)
|
||||
}
|
||||
|
||||
const query = params.filter ? `filter=${encodeURIComponent(params.filter)}` : undefined
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: '/v1/vaults',
|
||||
method: 'GET',
|
||||
query,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.message || 'Failed to list vaults' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] List vaults failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to list vaults: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
112
apps/sim/app/api/tools/onepassword/replace-item/route.ts
Normal file
112
apps/sim/app/api/tools/onepassword/replace-item/route.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
normalizeSdkItem,
|
||||
resolveCredentials,
|
||||
toSdkCategory,
|
||||
toSdkFieldType,
|
||||
} from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordReplaceItemAPI')
|
||||
|
||||
const ReplaceItemSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
vaultId: z.string().min(1, 'Vault ID is required'),
|
||||
itemId: z.string().min(1, 'Item ID is required'),
|
||||
item: z.string().min(1, 'Item JSON is required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password replace-item attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = ReplaceItemSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
const itemData = JSON.parse(params.item)
|
||||
|
||||
logger.info(
|
||||
`[${requestId}] Replacing item ${params.itemId} in vault ${params.vaultId} (${creds.mode} mode)`
|
||||
)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
|
||||
const sdkItem = {
|
||||
id: params.itemId,
|
||||
title: itemData.title || '',
|
||||
category: toSdkCategory(itemData.category || 'LOGIN'),
|
||||
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(),
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: `/v1/vaults/${params.vaultId}/items/${params.itemId}`,
|
||||
method: 'PUT',
|
||||
body: itemData,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.message || 'Failed to replace item' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] Replace item failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to replace item: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
59
apps/sim/app/api/tools/onepassword/resolve-secret/route.ts
Normal file
59
apps/sim/app/api/tools/onepassword/resolve-secret/route.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import { createOnePasswordClient, resolveCredentials } from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordResolveSecretAPI')
|
||||
|
||||
const ResolveSecretSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
secretReference: z.string().min(1, 'Secret reference is required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password resolve-secret attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = ResolveSecretSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
|
||||
if (creds.mode !== 'service_account') {
|
||||
return NextResponse.json(
|
||||
{ error: 'Resolve Secret is only available in Service Account mode' },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
logger.info(`[${requestId}] Resolving secret reference (service_account mode)`)
|
||||
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
const secret = await client.secrets.resolve(params.secretReference)
|
||||
|
||||
return NextResponse.json({
|
||||
secret,
|
||||
reference: params.secretReference,
|
||||
})
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] Resolve secret failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to resolve secret: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
135
apps/sim/app/api/tools/onepassword/update-item/route.ts
Normal file
135
apps/sim/app/api/tools/onepassword/update-item/route.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { checkInternalAuth } from '@/lib/auth/hybrid'
|
||||
import {
|
||||
connectRequest,
|
||||
createOnePasswordClient,
|
||||
normalizeSdkItem,
|
||||
resolveCredentials,
|
||||
} from '../utils'
|
||||
|
||||
const logger = createLogger('OnePasswordUpdateItemAPI')
|
||||
|
||||
const UpdateItemSchema = z.object({
|
||||
connectionMode: z.enum(['service_account', 'connect']).nullish(),
|
||||
serviceAccountToken: z.string().nullish(),
|
||||
serverUrl: z.string().nullish(),
|
||||
apiKey: z.string().nullish(),
|
||||
vaultId: z.string().min(1, 'Vault ID is required'),
|
||||
itemId: z.string().min(1, 'Item ID is required'),
|
||||
operations: z.string().min(1, 'Patch operations are required'),
|
||||
})
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const requestId = randomUUID().slice(0, 8)
|
||||
|
||||
const auth = await checkInternalAuth(request)
|
||||
if (!auth.success || !auth.userId) {
|
||||
logger.warn(`[${requestId}] Unauthorized 1Password update-item attempt`)
|
||||
return NextResponse.json({ error: auth.error || 'Unauthorized' }, { status: 401 })
|
||||
}
|
||||
|
||||
try {
|
||||
const body = await request.json()
|
||||
const params = UpdateItemSchema.parse(body)
|
||||
const creds = resolveCredentials(params)
|
||||
const ops = JSON.parse(params.operations) as Array<{
|
||||
op: string
|
||||
path: string
|
||||
value?: unknown
|
||||
}>
|
||||
|
||||
logger.info(
|
||||
`[${requestId}] Updating item ${params.itemId} in vault ${params.vaultId} (${creds.mode} mode)`
|
||||
)
|
||||
|
||||
if (creds.mode === 'service_account') {
|
||||
const client = await createOnePasswordClient(creds.serviceAccountToken!)
|
||||
|
||||
// SDK doesn't support PATCH — fetch, apply patches, then put
|
||||
const item = await client.items.get(params.vaultId, params.itemId)
|
||||
|
||||
for (const op of ops) {
|
||||
applyPatch(item, op)
|
||||
}
|
||||
|
||||
const result = await client.items.put(item)
|
||||
return NextResponse.json(normalizeSdkItem(result))
|
||||
}
|
||||
|
||||
const response = await connectRequest({
|
||||
serverUrl: creds.serverUrl!,
|
||||
apiKey: creds.apiKey!,
|
||||
path: `/v1/vaults/${params.vaultId}/items/${params.itemId}`,
|
||||
method: 'PATCH',
|
||||
body: ops,
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: data.message || 'Failed to update item' },
|
||||
{ status: response.status }
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json(data)
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Invalid request data', details: error.errors },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
const message = error instanceof Error ? error.message : 'Unknown error'
|
||||
logger.error(`[${requestId}] Update item failed:`, error)
|
||||
return NextResponse.json({ error: `Failed to update item: ${message}` }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply a single RFC6902 JSON Patch operation to a mutable SDK Item. */
|
||||
function applyPatch(item: Record<string, any>, op: { op: string; path: string; value?: unknown }) {
|
||||
const segments = op.path.split('/').filter(Boolean)
|
||||
|
||||
if (segments.length === 1) {
|
||||
const key = segments[0]
|
||||
if (op.op === 'replace' || op.op === 'add') {
|
||||
item[key] = op.value
|
||||
} else if (op.op === 'remove') {
|
||||
delete item[key]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Navigate to parent of target
|
||||
let target = item
|
||||
for (let i = 0; i < segments.length - 1; i++) {
|
||||
const seg = segments[i]
|
||||
if (Array.isArray(target)) {
|
||||
target = target[Number(seg)]
|
||||
} else {
|
||||
target = target[seg]
|
||||
}
|
||||
if (target === undefined || target === null) return
|
||||
}
|
||||
|
||||
const lastSeg = segments[segments.length - 1]
|
||||
|
||||
if (op.op === 'replace' || op.op === 'add') {
|
||||
if (Array.isArray(target) && lastSeg === '-') {
|
||||
target.push(op.value)
|
||||
} else if (Array.isArray(target)) {
|
||||
target[Number(lastSeg)] = op.value
|
||||
} else {
|
||||
target[lastSeg] = op.value
|
||||
}
|
||||
} else if (op.op === 'remove') {
|
||||
if (Array.isArray(target)) {
|
||||
target.splice(Number(lastSeg), 1)
|
||||
} else {
|
||||
delete target[lastSeg]
|
||||
}
|
||||
}
|
||||
}
|
||||
262
apps/sim/app/api/tools/onepassword/utils.ts
Normal file
262
apps/sim/app/api/tools/onepassword/utils.ts
Normal file
@@ -0,0 +1,262 @@
|
||||
import { createLogger } from '@sim/logger'
|
||||
|
||||
const logger = createLogger('OnePasswordRouteUtils')
|
||||
|
||||
/**
|
||||
* SDK field type string values → Connect field type mapping.
|
||||
* Uses string literals instead of enum imports to avoid loading the WASM module at build time.
|
||||
*/
|
||||
const SDK_TO_CONNECT_FIELD_TYPE: Record<string, string> = {
|
||||
Text: 'STRING',
|
||||
Concealed: 'CONCEALED',
|
||||
Email: 'EMAIL',
|
||||
Url: 'URL',
|
||||
Totp: 'OTP',
|
||||
Phone: 'PHONE',
|
||||
Date: 'DATE',
|
||||
MonthYear: 'MONTH_YEAR',
|
||||
Menu: 'MENU',
|
||||
Address: 'ADDRESS',
|
||||
Reference: 'REFERENCE',
|
||||
SshKey: 'SSHKEY',
|
||||
CreditCardNumber: 'CREDIT_CARD_NUMBER',
|
||||
CreditCardType: 'CREDIT_CARD_TYPE',
|
||||
}
|
||||
|
||||
/** SDK category string values → Connect category mapping. */
|
||||
const SDK_TO_CONNECT_CATEGORY: Record<string, string> = {
|
||||
Login: 'LOGIN',
|
||||
Password: 'PASSWORD',
|
||||
ApiCredentials: 'API_CREDENTIAL',
|
||||
SecureNote: 'SECURE_NOTE',
|
||||
Server: 'SERVER',
|
||||
Database: 'DATABASE',
|
||||
CreditCard: 'CREDIT_CARD',
|
||||
Identity: 'IDENTITY',
|
||||
SshKey: 'SSH_KEY',
|
||||
Document: 'DOCUMENT',
|
||||
SoftwareLicense: 'SOFTWARE_LICENSE',
|
||||
Email: 'EMAIL_ACCOUNT',
|
||||
Membership: 'MEMBERSHIP',
|
||||
Passport: 'PASSPORT',
|
||||
Rewards: 'REWARD_PROGRAM',
|
||||
DriverLicense: 'DRIVER_LICENSE',
|
||||
BankAccount: 'BANK_ACCOUNT',
|
||||
MedicalRecord: 'MEDICAL_RECORD',
|
||||
OutdoorLicense: 'OUTDOOR_LICENSE',
|
||||
Router: 'WIRELESS_ROUTER',
|
||||
SocialSecurityNumber: 'SOCIAL_SECURITY_NUMBER',
|
||||
CryptoWallet: 'CUSTOM',
|
||||
Person: 'CUSTOM',
|
||||
Unsupported: 'CUSTOM',
|
||||
}
|
||||
|
||||
/** Connect category → SDK category string mapping. */
|
||||
const CONNECT_TO_SDK_CATEGORY: Record<string, string> = {
|
||||
LOGIN: 'Login',
|
||||
PASSWORD: 'Password',
|
||||
API_CREDENTIAL: 'ApiCredentials',
|
||||
SECURE_NOTE: 'SecureNote',
|
||||
SERVER: 'Server',
|
||||
DATABASE: 'Database',
|
||||
CREDIT_CARD: 'CreditCard',
|
||||
IDENTITY: 'Identity',
|
||||
SSH_KEY: 'SshKey',
|
||||
DOCUMENT: 'Document',
|
||||
SOFTWARE_LICENSE: 'SoftwareLicense',
|
||||
EMAIL_ACCOUNT: 'Email',
|
||||
MEMBERSHIP: 'Membership',
|
||||
PASSPORT: 'Passport',
|
||||
REWARD_PROGRAM: 'Rewards',
|
||||
DRIVER_LICENSE: 'DriverLicense',
|
||||
BANK_ACCOUNT: 'BankAccount',
|
||||
MEDICAL_RECORD: 'MedicalRecord',
|
||||
OUTDOOR_LICENSE: 'OutdoorLicense',
|
||||
WIRELESS_ROUTER: 'Router',
|
||||
SOCIAL_SECURITY_NUMBER: 'SocialSecurityNumber',
|
||||
}
|
||||
|
||||
/** Connect field type → SDK field type string mapping. */
|
||||
const CONNECT_TO_SDK_FIELD_TYPE: Record<string, string> = {
|
||||
STRING: 'Text',
|
||||
CONCEALED: 'Concealed',
|
||||
EMAIL: 'Email',
|
||||
URL: 'Url',
|
||||
OTP: 'Totp',
|
||||
TOTP: 'Totp',
|
||||
PHONE: 'Phone',
|
||||
DATE: 'Date',
|
||||
MONTH_YEAR: 'MonthYear',
|
||||
MENU: 'Menu',
|
||||
ADDRESS: 'Address',
|
||||
REFERENCE: 'Reference',
|
||||
SSHKEY: 'SshKey',
|
||||
CREDIT_CARD_NUMBER: 'CreditCardNumber',
|
||||
CREDIT_CARD_TYPE: 'CreditCardType',
|
||||
}
|
||||
|
||||
export type ConnectionMode = 'service_account' | 'connect'
|
||||
|
||||
export interface CredentialParams {
|
||||
connectionMode?: ConnectionMode
|
||||
serviceAccountToken?: string
|
||||
serverUrl?: string
|
||||
apiKey?: string
|
||||
}
|
||||
|
||||
export interface ResolvedCredentials {
|
||||
mode: ConnectionMode
|
||||
serviceAccountToken?: string
|
||||
serverUrl?: string
|
||||
apiKey?: string
|
||||
}
|
||||
|
||||
/** Determine which backend to use based on provided credentials. */
|
||||
export function resolveCredentials(params: CredentialParams): ResolvedCredentials {
|
||||
const mode = params.connectionMode ?? (params.serviceAccountToken ? 'service_account' : 'connect')
|
||||
|
||||
if (mode === 'service_account') {
|
||||
if (!params.serviceAccountToken) {
|
||||
throw new Error('Service Account token is required for Service Account mode')
|
||||
}
|
||||
return { mode, serviceAccountToken: params.serviceAccountToken }
|
||||
}
|
||||
|
||||
if (!params.serverUrl || !params.apiKey) {
|
||||
throw new Error('Server URL and Connect token are required for Connect Server mode')
|
||||
}
|
||||
return { mode, serverUrl: params.serverUrl, apiKey: params.apiKey }
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a 1Password SDK client from a service account token.
|
||||
* Uses dynamic import to avoid loading the WASM module at build time.
|
||||
*/
|
||||
export async function createOnePasswordClient(serviceAccountToken: string) {
|
||||
const { createClient } = await import('@1password/sdk')
|
||||
return createClient({
|
||||
auth: serviceAccountToken,
|
||||
integrationName: 'Sim Studio',
|
||||
integrationVersion: '1.0.0',
|
||||
})
|
||||
}
|
||||
|
||||
/** Proxy a request to the 1Password Connect Server. */
|
||||
export async function connectRequest(options: {
|
||||
serverUrl: string
|
||||
apiKey: string
|
||||
path: string
|
||||
method: string
|
||||
body?: unknown
|
||||
query?: string
|
||||
}): Promise<Response> {
|
||||
const base = options.serverUrl.replace(/\/$/, '')
|
||||
const queryStr = options.query ? `?${options.query}` : ''
|
||||
const url = `${base}${options.path}${queryStr}`
|
||||
|
||||
const headers: Record<string, string> = {
|
||||
Authorization: `Bearer ${options.apiKey}`,
|
||||
}
|
||||
|
||||
if (options.body) {
|
||||
headers['Content-Type'] = 'application/json'
|
||||
}
|
||||
|
||||
logger.info(`Connect request: ${options.method} ${options.path}`)
|
||||
|
||||
return fetch(url, {
|
||||
method: options.method,
|
||||
headers,
|
||||
body: options.body ? JSON.stringify(options.body) : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
/** Normalize an SDK VaultOverview to match Connect API vault shape. */
|
||||
export function normalizeSdkVault(vault: Record<string, any>) {
|
||||
return {
|
||||
id: vault.id,
|
||||
name: vault.title,
|
||||
description: null,
|
||||
attributeVersion: 0,
|
||||
contentVersion: 0,
|
||||
items: 0,
|
||||
type: 'USER_CREATED',
|
||||
createdAt:
|
||||
vault.createdAt instanceof Date ? vault.createdAt.toISOString() : (vault.createdAt ?? null),
|
||||
updatedAt:
|
||||
vault.updatedAt instanceof Date ? vault.updatedAt.toISOString() : (vault.updatedAt ?? null),
|
||||
}
|
||||
}
|
||||
|
||||
/** Normalize an SDK ItemOverview to match Connect API item summary shape. */
|
||||
export function normalizeSdkItemOverview(item: Record<string, any>) {
|
||||
return {
|
||||
id: item.id,
|
||||
title: item.title,
|
||||
vault: { id: item.vaultId },
|
||||
category: SDK_TO_CONNECT_CATEGORY[item.category] ?? 'CUSTOM',
|
||||
urls: (item.websites ?? []).map((w: Record<string, any>) => ({
|
||||
href: w.url,
|
||||
label: w.label ?? null,
|
||||
primary: false,
|
||||
})),
|
||||
favorite: false,
|
||||
tags: item.tags ?? [],
|
||||
version: 0,
|
||||
state: item.state === 'archived' ? 'ARCHIVED' : null,
|
||||
createdAt:
|
||||
item.createdAt instanceof Date ? item.createdAt.toISOString() : (item.createdAt ?? null),
|
||||
updatedAt:
|
||||
item.updatedAt instanceof Date ? item.updatedAt.toISOString() : (item.updatedAt ?? null),
|
||||
lastEditedBy: null,
|
||||
}
|
||||
}
|
||||
|
||||
/** Normalize a full SDK Item to match Connect API FullItem shape. */
|
||||
export function normalizeSdkItem(item: Record<string, any>) {
|
||||
return {
|
||||
id: item.id,
|
||||
title: item.title,
|
||||
vault: { id: item.vaultId },
|
||||
category: SDK_TO_CONNECT_CATEGORY[item.category] ?? 'CUSTOM',
|
||||
urls: (item.websites ?? []).map((w: Record<string, any>) => ({
|
||||
href: w.url,
|
||||
label: w.label ?? null,
|
||||
primary: false,
|
||||
})),
|
||||
favorite: false,
|
||||
tags: item.tags ?? [],
|
||||
version: item.version ?? 0,
|
||||
state: null,
|
||||
fields: (item.fields ?? []).map((field: Record<string, any>) => ({
|
||||
id: field.id,
|
||||
label: field.title,
|
||||
type: SDK_TO_CONNECT_FIELD_TYPE[field.fieldType] ?? 'STRING',
|
||||
purpose: '',
|
||||
value: field.value ?? null,
|
||||
section: field.sectionId ? { id: field.sectionId } : null,
|
||||
generate: false,
|
||||
recipe: null,
|
||||
entropy: null,
|
||||
})),
|
||||
sections: (item.sections ?? []).map((section: Record<string, any>) => ({
|
||||
id: section.id,
|
||||
label: section.title,
|
||||
})),
|
||||
createdAt:
|
||||
item.createdAt instanceof Date ? item.createdAt.toISOString() : (item.createdAt ?? null),
|
||||
updatedAt:
|
||||
item.updatedAt instanceof Date ? item.updatedAt.toISOString() : (item.updatedAt ?? null),
|
||||
lastEditedBy: null,
|
||||
}
|
||||
}
|
||||
|
||||
/** Convert a Connect-style category string to the SDK category string. */
|
||||
export function toSdkCategory(category: string): string {
|
||||
return CONNECT_TO_SDK_CATEGORY[category] ?? 'Login'
|
||||
}
|
||||
|
||||
/** Convert a Connect-style field type string to the SDK field type string. */
|
||||
export function toSdkFieldType(type: string): string {
|
||||
return CONNECT_TO_SDK_FIELD_TYPE[type] ?? 'Text'
|
||||
}
|
||||
@@ -704,12 +704,10 @@ Return ONLY the comment text - no explanations.`,
|
||||
'jira_update',
|
||||
'jira_write',
|
||||
'jira_bulk_read',
|
||||
'jira_bulk_read_v2',
|
||||
'jira_delete_issue',
|
||||
'jira_assign_issue',
|
||||
'jira_transition_issue',
|
||||
'jira_search_issues',
|
||||
'jira_search_issues_v2',
|
||||
'jira_add_comment',
|
||||
'jira_get_comments',
|
||||
'jira_update_comment',
|
||||
@@ -737,7 +735,7 @@ Return ONLY the comment text - no explanations.`,
|
||||
case 'read':
|
||||
// If a project is selected but no issue is chosen, route to bulk read
|
||||
if (effectiveProjectId && !effectiveIssueKey) {
|
||||
return 'jira_bulk_read_v2'
|
||||
return 'jira_bulk_read'
|
||||
}
|
||||
return 'jira_retrieve'
|
||||
case 'update':
|
||||
@@ -745,7 +743,7 @@ Return ONLY the comment text - no explanations.`,
|
||||
case 'write':
|
||||
return 'jira_write'
|
||||
case 'read-bulk':
|
||||
return 'jira_bulk_read_v2'
|
||||
return 'jira_bulk_read'
|
||||
case 'delete':
|
||||
return 'jira_delete_issue'
|
||||
case 'assign':
|
||||
@@ -753,7 +751,7 @@ Return ONLY the comment text - no explanations.`,
|
||||
case 'transition':
|
||||
return 'jira_transition_issue'
|
||||
case 'search':
|
||||
return 'jira_search_issues_v2'
|
||||
return 'jira_search_issues'
|
||||
case 'add_comment':
|
||||
return 'jira_add_comment'
|
||||
case 'get_comments':
|
||||
@@ -1140,7 +1138,7 @@ Return ONLY the comment text - no explanations.`,
|
||||
id: { type: 'string', description: 'Jira issue ID' },
|
||||
key: { type: 'string', description: 'Jira issue key' },
|
||||
|
||||
// jira_search_issues_v2 / jira_bulk_read_v2 outputs
|
||||
// jira_search_issues / jira_bulk_read outputs
|
||||
total: { type: 'number', description: 'Total number of matching issues' },
|
||||
nextPageToken: { type: 'string', description: 'Cursor token for the next page of results' },
|
||||
isLast: { type: 'boolean', description: 'Whether this is the last page of results' },
|
||||
|
||||
@@ -6,7 +6,7 @@ export const OnePasswordBlock: BlockConfig = {
|
||||
name: '1Password',
|
||||
description: 'Manage secrets and items in 1Password vaults',
|
||||
longDescription:
|
||||
'Access and manage secrets stored in 1Password vaults using the Connect API. List vaults, retrieve items with their fields and secrets, create new items, update existing ones, and delete items.',
|
||||
'Access and manage secrets stored in 1Password vaults using the Connect API or Service Account SDK. List vaults, retrieve items with their fields and secrets, create new items, update existing ones, delete items, and resolve secret references.',
|
||||
docsLink: 'https://docs.sim.ai/tools/onepassword',
|
||||
category: 'tools',
|
||||
bgColor: '#E0E0E0',
|
||||
@@ -27,15 +27,36 @@ export const OnePasswordBlock: BlockConfig = {
|
||||
{ label: 'Replace Item', id: 'replace_item' },
|
||||
{ label: 'Update Item', id: 'update_item' },
|
||||
{ label: 'Delete Item', id: 'delete_item' },
|
||||
{ label: 'Resolve Secret', id: 'resolve_secret' },
|
||||
],
|
||||
value: () => 'get_item',
|
||||
},
|
||||
{
|
||||
id: 'connectionMode',
|
||||
title: 'Connection Mode',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'Service Account', id: 'service_account' },
|
||||
{ label: 'Connect Server', id: 'connect' },
|
||||
],
|
||||
value: () => 'service_account',
|
||||
},
|
||||
{
|
||||
id: 'serviceAccountToken',
|
||||
title: 'Service Account Token',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your 1Password Service Account token',
|
||||
password: true,
|
||||
required: { field: 'connectionMode', value: 'service_account' },
|
||||
condition: { field: 'connectionMode', value: 'service_account' },
|
||||
},
|
||||
{
|
||||
id: 'serverUrl',
|
||||
title: 'Server URL',
|
||||
type: 'short-input',
|
||||
placeholder: 'http://localhost:8080',
|
||||
required: true,
|
||||
required: { field: 'connectionMode', value: 'connect' },
|
||||
condition: { field: 'connectionMode', value: 'connect' },
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
@@ -43,7 +64,16 @@ export const OnePasswordBlock: BlockConfig = {
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your 1Password Connect token',
|
||||
password: true,
|
||||
required: true,
|
||||
required: { field: 'connectionMode', value: 'connect' },
|
||||
condition: { field: 'connectionMode', value: 'connect' },
|
||||
},
|
||||
{
|
||||
id: 'secretReference',
|
||||
title: 'Secret Reference',
|
||||
type: 'short-input',
|
||||
placeholder: 'op://vault-name/item-name/field-name',
|
||||
required: { field: 'operation', value: 'resolve_secret' },
|
||||
condition: { field: 'operation', value: 'resolve_secret' },
|
||||
},
|
||||
{
|
||||
id: 'vaultId',
|
||||
@@ -62,7 +92,11 @@ export const OnePasswordBlock: BlockConfig = {
|
||||
'delete_item',
|
||||
],
|
||||
},
|
||||
condition: { field: 'operation', value: 'list_vaults', not: true },
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['list_vaults', 'resolve_secret'],
|
||||
not: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'itemId',
|
||||
@@ -187,6 +221,7 @@ Return ONLY valid JSON - no explanations, no markdown code blocks.`,
|
||||
'onepassword_replace_item',
|
||||
'onepassword_update_item',
|
||||
'onepassword_delete_item',
|
||||
'onepassword_resolve_secret',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => `onepassword_${params.operation}`,
|
||||
@@ -195,8 +230,11 @@ Return ONLY valid JSON - no explanations, no markdown code blocks.`,
|
||||
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
connectionMode: { type: 'string', description: 'Connection mode: service_account or connect' },
|
||||
serviceAccountToken: { type: 'string', description: '1Password Service Account token' },
|
||||
serverUrl: { type: 'string', description: '1Password Connect server URL' },
|
||||
apiKey: { type: 'string', description: '1Password Connect token' },
|
||||
secretReference: { type: 'string', description: 'Secret reference URI (op://...)' },
|
||||
vaultId: { type: 'string', description: 'Vault UUID' },
|
||||
itemId: { type: 'string', description: 'Item UUID' },
|
||||
filter: { type: 'string', description: 'SCIM filter expression' },
|
||||
|
||||
@@ -33,21 +33,21 @@ export function AgentIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M15.6667 9.25H4.66667C2.64162 9.25 1 10.8916 1 12.9167V18.4167C1 20.4417 2.64162 22.0833 4.66667 22.0833H15.6667C17.6917 22.0833 19.3333 20.4417 19.3333 18.4167V12.9167C19.3333 10.8916 17.6917 9.25 15.6667 9.25Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M10.1663 5.58464C11.1789 5.58464 11.9997 4.76382 11.9997 3.7513C11.9997 2.73878 11.1789 1.91797 10.1663 1.91797C9.15382 1.91797 8.33301 2.73878 8.33301 3.7513C8.33301 4.76382 9.15382 5.58464 10.1663 5.58464Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M10.167 5.58594V9.2526M7.41699 16.5859V14.7526M12.917 14.7526V16.5859'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -68,7 +68,7 @@ export function ApiIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M5.61111 24.3889C8.5 27.2778 12.4722 25.4722 13.5556 24.3889L15.7222 22.2222L7.77778 14.2778L5.61111 16.4444C4.52778 17.5278 2.72222 21.5 5.61111 24.3889ZM5.61111 24.3889L2 28M24.3889 5.61111C21.5 2.72222 17.5278 4.52778 16.4444 5.61111L14.2778 7.77778L22.2222 15.7222L24.3889 13.5556C25.4722 12.4722 27.2778 8.5 24.3889 5.61111ZM24.3889 5.61111L28 2M15.7222 9.22222L12.8333 12.1111M20.7778 14.2778L17.8889 17.1667'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -90,7 +90,7 @@ export function ConditionalIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<path
|
||||
d='M23.1015 1.01616C22.1825 1.01442 21.2926 1.33795 20.5894 1.92946C19.8861 2.52098 19.4149 3.34229 19.2592 4.24794C19.1035 5.15358 19.2733 6.08512 19.7386 6.87755C20.2039 7.66998 20.9346 8.27217 21.8014 8.57745V12.7169H6.20035V8.57745C7.06779 8.27077 7.79888 7.6673 8.26441 6.87372C8.72994 6.08013 8.89994 5.14752 8.74435 4.24072C8.58877 3.33391 8.11762 2.5113 7.41419 1.91828C6.71075 1.32526 5.82032 1 4.90027 1C3.98021 1 3.08978 1.32526 2.38634 1.91828C1.68291 2.5113 1.21176 3.33391 1.05618 4.24072C0.900594 5.14752 1.07059 6.08013 1.53612 6.87372C2.00165 7.6673 2.73274 8.27077 3.60018 8.57745V12.7169C3.60018 13.4065 3.87413 14.0679 4.36175 14.5555C4.84938 15.0432 5.51074 15.3171 6.20035 15.3171H12.7008V20.7567C11.8333 21.0633 11.1023 21.6668 10.6367 22.4604C10.1712 23.254 10.0012 24.1866 10.1568 25.0934C10.3124 26.0002 10.7835 26.8228 11.4869 27.4158C12.1904 28.0089 13.0808 28.3341 14.0009 28.3341C14.9209 28.3341 15.8114 28.0089 16.5148 27.4158C17.2182 26.8228 17.6894 26.0002 17.845 25.0934C18.0005 24.1866 17.8305 23.254 17.365 22.4604C16.8995 21.6668 16.1684 21.0633 15.301 20.7567V15.3171H21.8014C22.491 15.3171 23.1524 15.0432 23.64 14.5555C24.1276 14.0679 24.4015 13.4065 24.4015 12.7169V8.57745C25.2683 8.27217 25.999 7.66998 26.4643 6.87755C26.9296 6.08512 27.0994 5.15358 26.9437 4.24794C26.788 3.34229 26.3168 2.52098 25.6135 1.92946C24.9103 1.33795 24.0204 1.01442 23.1015 1.01616ZM4.90027 6.2165C4.64313 6.2165 4.39177 6.14025 4.17798 5.99739C3.96418 5.85454 3.79754 5.65149 3.69914 5.41393C3.60074 5.17637 3.575 4.91497 3.62516 4.66278C3.67532 4.41059 3.79915 4.17893 3.98097 3.99711C4.16279 3.81529 4.39444 3.69147 4.64663 3.64131C4.89882 3.59114 5.16023 3.61689 5.39779 3.71529C5.63535 3.81369 5.83839 3.98033 5.98125 4.19412C6.1241 4.40792 6.20035 4.65928 6.20035 4.91641C6.20035 5.26122 6.06338 5.5919 5.81956 5.83571C5.57575 6.07953 5.24507 6.2165 4.90027 6.2165ZM14.0009 25.7178C13.7437 25.7178 13.4924 25.6415 13.2786 25.4987C13.0648 25.3558 12.8981 25.1528 12.7997 24.9152C12.7013 24.6777 12.6756 24.4163 12.7258 24.1641C12.7759 23.9119 12.8997 23.6802 13.0816 23.4984C13.2634 23.3166 13.495 23.1928 13.7472 23.1426C13.9994 23.0924 14.2608 23.1182 14.4984 23.2166C14.7359 23.315 14.939 23.4816 15.0818 23.6954C15.2247 23.9092 15.301 24.1606 15.301 24.4177C15.301 24.7625 15.164 25.0932 14.9202 25.337C14.6764 25.5808 14.3457 25.7178 14.0009 25.7178ZM23.1015 6.2165C22.8443 6.2165 22.593 6.14025 22.3792 5.99739C22.1654 5.85454 21.9987 5.65149 21.9003 5.41393C21.8019 5.17637 21.7762 4.91497 21.8264 4.66278C21.8765 4.41059 22.0003 4.17893 22.1822 3.99711C22.364 3.81529 22.5956 3.69147 22.8478 3.64131C23.1 3.59114 23.3614 3.61689 23.599 3.71529C23.8365 3.81369 24.0396 3.98033 24.1824 4.19412C24.3253 4.40792 24.4015 4.65928 24.4015 4.91641C24.4015 5.26122 24.2646 5.5919 24.0208 5.83571C23.777 6.07953 23.4463 6.2165 23.1015 6.2165Z'
|
||||
fill='currentColor'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='0.25'
|
||||
/>
|
||||
</svg>
|
||||
@@ -113,7 +113,7 @@ export function NoteIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='16'
|
||||
height='18'
|
||||
rx='2.5'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
fill='none'
|
||||
/>
|
||||
@@ -139,7 +139,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
cx='12'
|
||||
cy='6'
|
||||
r='3'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -151,7 +151,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='8'
|
||||
x='2'
|
||||
y='16'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -163,7 +163,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='8'
|
||||
x='14'
|
||||
y='16'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -171,7 +171,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<path
|
||||
className='a'
|
||||
d='M6,16V14a2,2,0,0,1,2-2h8a2,2,0,0,1,2,2v2'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -182,7 +182,7 @@ export function WorkflowIcon(props: SVGProps<SVGSVGElement>) {
|
||||
x2='12'
|
||||
y1='9'
|
||||
y2='12'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='1.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -203,7 +203,7 @@ export function SignalIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M23.964 33.2C26.252 28.416 27.5 23.216 27.5 17.6C27.5 11.984 26.252 6.576 23.964 2M16.476 29.664C18.14 25.92 19.18 21.76 19.18 17.6C19.18 13.44 18.14 9.072 16.476 5.328M8.988 26.128C10.236 23.424 10.86 20.512 10.86 17.6C10.86 14.688 10.236 11.568 8.988 9.072M1.5 22.384C2.124 20.928 2.54 19.264 2.54 17.6C2.54 15.936 2.124 14.064 1.5 12.608'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -224,7 +224,7 @@ export function CalendarIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M21.5 4.88889V2M8.5 4.88889V2M2.36111 9.22222H27.6389M2 12.1747C2 9.11967 2 7.59144 2.62978 6.42433C3.19924 5.38333 4.08288 4.54873 5.15467 4.03956C6.39111 3.44444 8.00889 3.44444 11.2444 3.44444H18.7556C21.9911 3.44444 23.6089 3.44444 24.8453 4.03956C25.933 4.56244 26.8156 5.39733 27.3702 6.42289C28 7.59289 28 9.12111 28 12.1761V19.2712C28 22.3262 28 23.8544 27.3702 25.0216C26.8008 26.0626 25.9171 26.8972 24.8453 27.4063C23.6089 28 21.9911 28 18.7556 28H11.2444C8.00889 28 6.39111 28 5.15467 27.4049C4.0831 26.8961 3.19948 26.062 2.62978 25.0216C2 23.8516 2 22.3233 2 19.2683V12.1747Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -245,7 +245,7 @@ export function MessagesIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M4.88867 14.999C6.27936 13.956 7.99961 13.4496 9.7336 13.5728C11.4676 13.6961 13.0989 14.4406 14.3281 15.6698C15.5574 16.899 16.3019 18.5304 16.4252 20.2644C16.5484 21.9984 16.042 23.7186 14.999 25.1093M4.88867 14.999C3.99176 15.6717 3.2638 16.5439 2.76241 17.5467C2.26103 18.5495 2 19.6552 2 20.7763C1.99954 21.5025 2.10861 22.2246 2.32353 22.9183C2.71639 24.1893 2.4333 25.6047 2.18054 26.9393C2.15813 27.0534 2.16551 27.1713 2.20198 27.2817C2.23845 27.392 2.30278 27.4912 2.38874 27.5694C2.4747 27.6477 2.57939 27.7025 2.6927 27.7285C2.80601 27.7544 2.92411 27.7508 3.03559 27.7178C4.26038 27.3827 5.47795 27.0967 6.72875 27.556C7.52721 27.849 8.37115 27.9986 9.22166 27.998C10.343 27.9991 11.4491 27.7386 12.4521 27.2371C13.455 26.7356 14.3271 26.0071 14.999 25.1093M4.88867 14.999C4.88867 8.23229 9.04112 2 16.4433 2C18.2963 1.99968 20.1222 2.44502 21.767 3.29845C23.4118 4.15189 24.8272 5.38838 25.8938 6.90363C26.9605 8.41888 27.647 10.1684 27.8956 12.0047C28.1441 13.841 27.9474 15.7101 27.322 17.4544C26.6345 19.3695 27.3755 21.9347 27.8088 24.0521C27.834 24.1648 27.8288 24.2822 27.7937 24.3923C27.7587 24.5024 27.6949 24.6011 27.6091 24.6785C27.5232 24.7558 27.4184 24.8089 27.3052 24.8323C27.1921 24.8557 27.0748 24.8486 26.9653 24.8118C25.0703 24.2196 22.846 23.3877 21.0652 24.1387C19.1384 24.9504 17.1135 25.1093 14.999 25.1093'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -266,7 +266,7 @@ export function NotificationsIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M19.9056 24.7496H10.0908M19.9056 24.7496H25.7783C28.8267 24.7496 28.3116 21.7272 26.7695 20.1932C21.2153 14.6764 29.1046 2 14.9982 2C0.891783 2 8.78265 14.6748 3.22849 20.1932C1.74489 21.6687 1.11278 24.7496 4.21973 24.7496H10.0908M19.9056 24.7496C19.9056 27.8777 18.8526 31.2495 14.9982 31.2495C11.1437 31.2495 10.0908 27.8777 10.0908 24.7496'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -287,7 +287,7 @@ export function MailIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M2.35742 5.83288L11.7674 12.1071C13.0656 12.9712 13.7141 13.404 14.4151 13.5725C15.0352 13.7208 15.681 13.7208 16.2998 13.5725C17.0008 13.404 17.6492 12.9712 18.9475 12.1071L28.3574 5.83288M8.82844 21.7219H21.8864C24.1513 21.7219 25.2837 21.7219 26.1492 21.2811C26.9097 20.8931 27.5278 20.2744 27.9152 19.5137C28.3574 18.6482 28.3574 17.5158 28.3574 15.2509V7.97102C28.3574 5.70616 28.3574 4.57373 27.9166 3.70823C27.5288 2.94727 26.9102 2.32858 26.1492 1.94084C25.2837 1.5 24.1513 1.5 21.8864 1.5H8.82844C6.56358 1.5 5.43115 1.5 4.56566 1.94084C3.80519 2.32881 3.187 2.94747 2.79961 3.70823C2.35742 4.57373 2.35742 5.70616 2.35742 7.97102V15.2509C2.35742 17.5158 2.35742 18.6482 2.79826 19.5137C3.186 20.2747 3.80469 20.8933 4.56566 21.2811C5.43115 21.7219 6.56358 21.7219 8.82844 21.7219Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -312,25 +312,33 @@ export function MailServerIcon(props: SVGProps<SVGSVGElement>) {
|
||||
width='18'
|
||||
height='16'
|
||||
rx='2'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M3 8L10.89 13.26C11.2187 13.4793 11.6049 13.5963 12 13.5963C12.3951 13.5963 12.7813 13.4793 13.11 13.26L21 8'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<line x1='7' y1='16' x2='7' y2='16' stroke='#000000' strokeWidth='2' strokeLinecap='round' />
|
||||
<line
|
||||
x1='7'
|
||||
y1='16'
|
||||
x2='7'
|
||||
y2='16'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
/>
|
||||
<line
|
||||
x1='10'
|
||||
y1='16'
|
||||
x2='10'
|
||||
y2='16'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
/>
|
||||
@@ -350,7 +358,7 @@ export function CodeIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M23.2639 6.83064L23.6375 7.20422C26.5433 10.1117 27.9971 11.5638 27.9971 13.37C27.9971 15.1762 26.5433 16.63 23.6375 19.5358L23.2639 19.9094M18.0434 2L11.9507 24.7401M6.72863 6.83064L6.35504 7.20422C3.45081 10.1117 1.99707 11.5638 1.99707 13.37C1.99707 15.1762 3.45081 16.63 6.35829 19.5358L6.73187 19.9094'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.6'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -837,7 +845,7 @@ export function xIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<path
|
||||
d='M 5.9199219 6 L 20.582031 27.375 L 6.2304688 44 L 9.4101562 44 L 21.986328 29.421875 L 31.986328 44 L 44 44 L 28.681641 21.669922 L 42.199219 6 L 39.029297 6 L 27.275391 19.617188 L 17.933594 6 L 5.9199219 6 z M 9.7167969 8 L 16.880859 8 L 40.203125 42 L 33.039062 42 L 9.7167969 8 z'
|
||||
fill='currentColor'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='0.5'
|
||||
/>
|
||||
</svg>
|
||||
@@ -1491,14 +1499,14 @@ export function DocumentIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M8 15.2H15.2M8 20H11.6M2 4.4V23.6C2 24.2365 2.25286 24.847 2.70294 25.2971C3.15303 25.7471 3.76348 26 4.4 26H18.8C19.4365 26 20.047 25.7471 20.4971 25.2971C20.9471 24.847 21.2 24.2365 21.2 23.6V9.6104C21.2 9.29067 21.136 8.97417 21.012 8.67949C20.8879 8.38481 20.7062 8.11789 20.4776 7.8944L15.1496 2.684C14.7012 2.24559 14.0991 2.00008 13.472 2H4.4C3.76348 2 3.15303 2.25286 2.70294 2.70294C2.25286 3.15303 2 3.76348 2 4.4Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.25'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M14 2V6.8C14 7.43652 14.2529 8.04697 14.7029 8.49706C15.153 8.94714 15.7635 9.2 16.4 9.2H21.2'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.25'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
@@ -3993,7 +4001,7 @@ export function SmtpIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M2.35742 5.83288L11.7674 12.1071C13.0656 12.9712 13.7141 13.404 14.4151 13.5725C15.0352 13.7208 15.681 13.7208 16.2998 13.5725C17.0008 13.404 17.6492 12.9712 18.9475 12.1071L28.3574 5.83288M8.82844 21.7219H21.8864C24.1513 21.7219 25.2837 21.7219 26.1492 21.2811C26.9097 20.8931 27.5278 20.2744 27.9152 19.5137C28.3574 18.6482 28.3574 17.5158 28.3574 15.2509V7.97102C28.3574 5.70616 28.3574 4.57373 27.9166 3.70823C27.5288 2.94727 26.9102 2.32858 26.1492 1.94084C25.2837 1.5 24.1513 1.5 21.8864 1.5H8.82844C6.56358 1.5 5.43115 1.5 4.56566 1.94084C3.80519 2.32881 3.187 2.94747 2.79961 3.70823C2.35742 4.57373 2.35742 5.70616 2.35742 7.97102V15.2509C2.35742 17.5158 2.35742 18.6482 2.79826 19.5137C3.186 20.2747 3.80469 20.8933 4.56566 21.2811C5.43115 21.7219 6.56358 21.7219 8.82844 21.7219Z'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2.5'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
@@ -4219,7 +4227,7 @@ export function A2AIcon(props: SVGProps<SVGSVGElement>) {
|
||||
<circle cx='316' cy='307' r='27' fill='currentColor' />
|
||||
<path
|
||||
d='M336.5 191.003H162C97.6588 191.003 45.5 243.162 45.5 307.503C45.5 371.844 97.6442 424.003 161.985 424.003C206.551 424.003 256.288 424.003 296.5 424.003C487.5 424.003 374 191.005 569 191.001C613.886 191 658.966 191 698.025 191C762.366 191.001 814.5 243.16 814.5 307.501C814.5 371.843 762.34 424.003 697.998 424.003H523.5'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='48'
|
||||
strokeLinecap='round'
|
||||
/>
|
||||
@@ -4489,14 +4497,14 @@ export function RssIcon(props: SVGProps<SVGSVGElement>) {
|
||||
>
|
||||
<path
|
||||
d='M4 11C6.38695 11 8.67613 11.9482 10.364 13.636C12.0518 15.3239 13 17.6131 13 20'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
/>
|
||||
<path
|
||||
d='M4 4C8.24346 4 12.3131 5.68571 15.3137 8.68629C18.3143 11.6869 20 15.7565 20 20'
|
||||
stroke='#000000'
|
||||
stroke='currentColor'
|
||||
strokeWidth='2'
|
||||
strokeLinecap='round'
|
||||
strokeLinejoin='round'
|
||||
|
||||
@@ -77,6 +77,7 @@ const nextConfig: NextConfig = {
|
||||
resolveExtensions: ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.json'],
|
||||
},
|
||||
serverExternalPackages: [
|
||||
'@1password/sdk',
|
||||
'unpdf',
|
||||
'ffmpeg-static',
|
||||
'fluent-ffmpeg',
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"generate-docs": "bun run ../../scripts/generate-docs.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@1password/sdk": "0.3.1",
|
||||
"@a2a-js/sdk": "0.3.7",
|
||||
"@anthropic-ai/sdk": "0.71.2",
|
||||
"@aws-sdk/client-bedrock-runtime": "3.940.0",
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import type {
|
||||
JiraRetrieveBulkParams,
|
||||
JiraRetrieveBulkV2Params,
|
||||
JiraRetrieveResponseBulk,
|
||||
JiraRetrieveResponseBulkV2,
|
||||
} from '@/tools/jira/types'
|
||||
import type { JiraRetrieveBulkParams, JiraRetrieveResponseBulk } from '@/tools/jira/types'
|
||||
import { TIMESTAMP_OUTPUT } from '@/tools/jira/types'
|
||||
import { extractAdfText } from '@/tools/jira/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
@@ -90,218 +85,7 @@ export const jiraBulkRetrieveTool: ToolConfig<JiraRetrieveBulkParams, JiraRetrie
|
||||
const projectKey = await resolveProjectKey(cloudId, params!.accessToken, params!.projectId)
|
||||
const jql = `project = ${projectKey} ORDER BY updated DESC`
|
||||
|
||||
let startAt = 0
|
||||
let collected: any[] = []
|
||||
let total = 0
|
||||
|
||||
while (startAt < MAX_TOTAL) {
|
||||
const queryParams = new URLSearchParams({
|
||||
jql,
|
||||
fields: 'summary,description,status,issuetype,priority,assignee,created,updated',
|
||||
maxResults: String(PAGE_SIZE),
|
||||
})
|
||||
if (startAt > 0) queryParams.set('startAt', String(startAt))
|
||||
|
||||
const url = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/search/jql?${queryParams.toString()}`
|
||||
const pageResponse = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Authorization: `Bearer ${params!.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
const pageData = await pageResponse.json()
|
||||
const issues = pageData.issues || []
|
||||
total = pageData.total || issues.length
|
||||
collected = collected.concat(issues)
|
||||
|
||||
if (collected.length >= Math.min(total, MAX_TOTAL) || issues.length === 0) break
|
||||
startAt += PAGE_SIZE
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
total,
|
||||
issues: collected.slice(0, MAX_TOTAL).map((issue: any) => ({
|
||||
id: issue.id ?? '',
|
||||
key: issue.key ?? '',
|
||||
self: issue.self ?? '',
|
||||
summary: issue.fields?.summary ?? '',
|
||||
description: extractAdfText(issue.fields?.description),
|
||||
status: {
|
||||
id: issue.fields?.status?.id ?? '',
|
||||
name: issue.fields?.status?.name ?? '',
|
||||
},
|
||||
issuetype: {
|
||||
id: issue.fields?.issuetype?.id ?? '',
|
||||
name: issue.fields?.issuetype?.name ?? '',
|
||||
},
|
||||
priority: issue.fields?.priority
|
||||
? { id: issue.fields.priority.id ?? '', name: issue.fields.priority.name ?? '' }
|
||||
: null,
|
||||
assignee: issue.fields?.assignee
|
||||
? {
|
||||
accountId: issue.fields.assignee.accountId ?? '',
|
||||
displayName: issue.fields.assignee.displayName ?? '',
|
||||
}
|
||||
: null,
|
||||
created: issue.fields?.created ?? '',
|
||||
updated: issue.fields?.updated ?? '',
|
||||
})),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
total: { type: 'number', description: 'Total number of issues in the project' },
|
||||
issues: {
|
||||
type: 'array',
|
||||
description: 'Array of Jira issues',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Issue ID' },
|
||||
key: { type: 'string', description: 'Issue key (e.g., PROJ-123)' },
|
||||
self: { type: 'string', description: 'REST API URL for this issue' },
|
||||
summary: { type: 'string', description: 'Issue summary' },
|
||||
description: { type: 'string', description: 'Issue description text', optional: true },
|
||||
status: {
|
||||
type: 'object',
|
||||
description: 'Issue status',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Status ID' },
|
||||
name: { type: 'string', description: 'Status name' },
|
||||
},
|
||||
},
|
||||
issuetype: {
|
||||
type: 'object',
|
||||
description: 'Issue type',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Issue type ID' },
|
||||
name: { type: 'string', description: 'Issue type name' },
|
||||
},
|
||||
},
|
||||
priority: {
|
||||
type: 'object',
|
||||
description: 'Issue priority',
|
||||
properties: {
|
||||
id: { type: 'string', description: 'Priority ID' },
|
||||
name: { type: 'string', description: 'Priority name' },
|
||||
},
|
||||
optional: true,
|
||||
},
|
||||
assignee: {
|
||||
type: 'object',
|
||||
description: 'Assigned user',
|
||||
properties: {
|
||||
accountId: { type: 'string', description: 'Atlassian account ID' },
|
||||
displayName: { type: 'string', description: 'Display name' },
|
||||
},
|
||||
optional: true,
|
||||
},
|
||||
created: { type: 'string', description: 'ISO 8601 creation timestamp' },
|
||||
updated: { type: 'string', description: 'ISO 8601 last updated timestamp' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* V2 Bulk Read Tool - Uses cursor-based pagination (nextPageToken) on /rest/api/3/search/jql.
|
||||
* The startAt parameter was deprecated on this endpoint as of Sept 2025.
|
||||
*/
|
||||
export const jiraBulkRetrieveV2Tool: ToolConfig<
|
||||
JiraRetrieveBulkV2Params,
|
||||
JiraRetrieveResponseBulkV2
|
||||
> = {
|
||||
id: 'jira_bulk_read_v2',
|
||||
name: 'Jira Bulk Read V2',
|
||||
description:
|
||||
'Retrieve multiple Jira issues from a project in bulk with cursor-based pagination (V2 - uses nextPageToken)',
|
||||
version: '2.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'jira',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Jira',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Jira domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Jira project key (e.g., PROJ)',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'hidden',
|
||||
description:
|
||||
'Jira Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: () => 'https://api.atlassian.com/oauth/token/accessible-resources',
|
||||
method: 'GET',
|
||||
headers: (params: JiraRetrieveBulkV2Params) => ({
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
Accept: 'application/json',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: JiraRetrieveBulkV2Params) => {
|
||||
const MAX_TOTAL = 1000
|
||||
const PAGE_SIZE = 100
|
||||
|
||||
const resolveProjectKey = async (cloudId: string, accessToken: string, ref: string) => {
|
||||
const refTrimmed = (ref || '').trim()
|
||||
if (!refTrimmed) return refTrimmed
|
||||
const url = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/project/${encodeURIComponent(refTrimmed)}`
|
||||
const resp = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json' },
|
||||
})
|
||||
if (!resp.ok) return refTrimmed
|
||||
const project = await resp.json()
|
||||
return project?.key || refTrimmed
|
||||
}
|
||||
|
||||
const resolveCloudId = async () => {
|
||||
if (params?.cloudId) return params.cloudId
|
||||
const accessibleResources = await response.json()
|
||||
const normalizedInput = `https://${params?.domain}`.toLowerCase()
|
||||
const matchedResource = accessibleResources.find(
|
||||
(r: { url: string }) => r.url.toLowerCase() === normalizedInput
|
||||
)
|
||||
if (matchedResource) return matchedResource.id
|
||||
if (Array.isArray(accessibleResources) && accessibleResources.length > 0)
|
||||
return accessibleResources[0].id
|
||||
throw new Error('No Jira resources found')
|
||||
}
|
||||
|
||||
const cloudId = await resolveCloudId()
|
||||
const projectKey = await resolveProjectKey(cloudId, params!.accessToken, params!.projectId)
|
||||
const jql = `project = ${projectKey} ORDER BY updated DESC`
|
||||
|
||||
let collected: Array<Record<string, unknown>> = []
|
||||
let nextPageToken: string | undefined
|
||||
let total: number | null = null
|
||||
|
||||
@@ -344,51 +128,46 @@ export const jiraBulkRetrieveV2Tool: ToolConfig<
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
issues: collected.slice(0, MAX_TOTAL).map((issue: Record<string, unknown>) => {
|
||||
const fields = (issue.fields as Record<string, unknown>) ?? {}
|
||||
const status = fields.status as Record<string, unknown> | undefined
|
||||
const issuetype = fields.issuetype as Record<string, unknown> | undefined
|
||||
const priority = fields.priority as Record<string, unknown> | undefined
|
||||
const assignee = fields.assignee as Record<string, unknown> | undefined
|
||||
return {
|
||||
id: (issue.id as string) ?? '',
|
||||
key: (issue.key as string) ?? '',
|
||||
self: (issue.self as string) ?? '',
|
||||
summary: (fields.summary as string) ?? '',
|
||||
description: extractAdfText(fields.description),
|
||||
status: {
|
||||
id: (status?.id as string) ?? '',
|
||||
name: (status?.name as string) ?? '',
|
||||
},
|
||||
issuetype: {
|
||||
id: (issuetype?.id as string) ?? '',
|
||||
name: (issuetype?.name as string) ?? '',
|
||||
},
|
||||
priority: priority
|
||||
? {
|
||||
id: (priority.id as string) ?? '',
|
||||
name: (priority.name as string) ?? '',
|
||||
}
|
||||
: null,
|
||||
assignee: assignee
|
||||
? {
|
||||
accountId: (assignee.accountId as string) ?? '',
|
||||
displayName: (assignee.displayName as string) ?? '',
|
||||
}
|
||||
: null,
|
||||
created: (fields.created as string) ?? '',
|
||||
updated: (fields.updated as string) ?? '',
|
||||
}
|
||||
}),
|
||||
total,
|
||||
issues: collected.slice(0, MAX_TOTAL).map((issue: any) => ({
|
||||
id: issue.id ?? '',
|
||||
key: issue.key ?? '',
|
||||
self: issue.self ?? '',
|
||||
summary: issue.fields?.summary ?? '',
|
||||
description: extractAdfText(issue.fields?.description),
|
||||
status: {
|
||||
id: issue.fields?.status?.id ?? '',
|
||||
name: issue.fields?.status?.name ?? '',
|
||||
},
|
||||
issuetype: {
|
||||
id: issue.fields?.issuetype?.id ?? '',
|
||||
name: issue.fields?.issuetype?.name ?? '',
|
||||
},
|
||||
priority: issue.fields?.priority
|
||||
? { id: issue.fields.priority.id ?? '', name: issue.fields.priority.name ?? '' }
|
||||
: null,
|
||||
assignee: issue.fields?.assignee
|
||||
? {
|
||||
accountId: issue.fields.assignee.accountId ?? '',
|
||||
displayName: issue.fields.assignee.displayName ?? '',
|
||||
}
|
||||
: null,
|
||||
created: issue.fields?.created ?? '',
|
||||
updated: issue.fields?.updated ?? '',
|
||||
})),
|
||||
nextPageToken: nextPageToken ?? null,
|
||||
isLast: !nextPageToken || collected.length >= MAX_TOTAL,
|
||||
total,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of issues in the project (may not always be available)',
|
||||
optional: true,
|
||||
},
|
||||
issues: {
|
||||
type: 'array',
|
||||
description: 'Array of Jira issues',
|
||||
@@ -445,10 +224,5 @@ export const jiraBulkRetrieveV2Tool: ToolConfig<
|
||||
optional: true,
|
||||
},
|
||||
isLast: { type: 'boolean', description: 'Whether this is the last page of results' },
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of issues in the project (may not always be available)',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { jiraAddCommentTool } from '@/tools/jira/add_comment'
|
||||
import { jiraAddWatcherTool } from '@/tools/jira/add_watcher'
|
||||
import { jiraAddWorklogTool } from '@/tools/jira/add_worklog'
|
||||
import { jiraAssignIssueTool } from '@/tools/jira/assign_issue'
|
||||
import { jiraBulkRetrieveTool, jiraBulkRetrieveV2Tool } from '@/tools/jira/bulk_read'
|
||||
import { jiraBulkRetrieveTool } from '@/tools/jira/bulk_read'
|
||||
import { jiraCreateIssueLinkTool } from '@/tools/jira/create_issue_link'
|
||||
import { jiraDeleteAttachmentTool } from '@/tools/jira/delete_attachment'
|
||||
import { jiraDeleteCommentTool } from '@/tools/jira/delete_comment'
|
||||
@@ -16,7 +16,7 @@ import { jiraGetUsersTool } from '@/tools/jira/get_users'
|
||||
import { jiraGetWorklogsTool } from '@/tools/jira/get_worklogs'
|
||||
import { jiraRemoveWatcherTool } from '@/tools/jira/remove_watcher'
|
||||
import { jiraRetrieveTool } from '@/tools/jira/retrieve'
|
||||
import { jiraSearchIssuesTool, jiraSearchIssuesV2Tool } from '@/tools/jira/search_issues'
|
||||
import { jiraSearchIssuesTool } from '@/tools/jira/search_issues'
|
||||
import { jiraTransitionIssueTool } from '@/tools/jira/transition_issue'
|
||||
import { jiraUpdateTool } from '@/tools/jira/update'
|
||||
import { jiraUpdateCommentTool } from '@/tools/jira/update_comment'
|
||||
@@ -28,12 +28,10 @@ export {
|
||||
jiraUpdateTool,
|
||||
jiraWriteTool,
|
||||
jiraBulkRetrieveTool,
|
||||
jiraBulkRetrieveV2Tool,
|
||||
jiraDeleteIssueTool,
|
||||
jiraAssignIssueTool,
|
||||
jiraTransitionIssueTool,
|
||||
jiraSearchIssuesTool,
|
||||
jiraSearchIssuesV2Tool,
|
||||
jiraAddCommentTool,
|
||||
jiraAddAttachmentTool,
|
||||
jiraGetCommentsTool,
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
import type {
|
||||
JiraSearchIssuesParams,
|
||||
JiraSearchIssuesResponse,
|
||||
JiraSearchIssuesV2Params,
|
||||
JiraSearchIssuesV2Response,
|
||||
} from '@/tools/jira/types'
|
||||
import type { JiraSearchIssuesParams, JiraSearchIssuesResponse } from '@/tools/jira/types'
|
||||
import { SEARCH_ISSUE_ITEM_PROPERTIES, TIMESTAMP_OUTPUT } from '@/tools/jira/types'
|
||||
import { extractAdfText, getJiraCloudId, transformUser } from '@/tools/jira/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
@@ -71,173 +66,6 @@ export const jiraSearchIssuesTool: ToolConfig<JiraSearchIssuesParams, JiraSearch
|
||||
provider: 'jira',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'hidden',
|
||||
description: 'OAuth access token for Jira',
|
||||
},
|
||||
domain: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'Your Jira domain (e.g., yourcompany.atlassian.net)',
|
||||
},
|
||||
jql: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'JQL query string to search for issues (e.g., "project = PROJ AND status = Open")',
|
||||
},
|
||||
startAt: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'The index of the first result to return (for pagination)',
|
||||
},
|
||||
maxResults: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Maximum number of results to return (default: 50)',
|
||||
},
|
||||
fields: {
|
||||
type: 'array',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Array of field names to return (default: all navigable). Use "*all" for every field.',
|
||||
},
|
||||
cloudId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'hidden',
|
||||
description:
|
||||
'Jira Cloud ID for the instance. If not provided, it will be fetched using the domain.',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: JiraSearchIssuesParams) => {
|
||||
if (params.cloudId) {
|
||||
const query = new URLSearchParams()
|
||||
if (params.jql) query.set('jql', params.jql)
|
||||
if (typeof params.startAt === 'number') query.set('startAt', String(params.startAt))
|
||||
if (typeof params.maxResults === 'number')
|
||||
query.set('maxResults', String(params.maxResults))
|
||||
if (Array.isArray(params.fields) && params.fields.length > 0)
|
||||
query.set('fields', params.fields.join(','))
|
||||
const qs = query.toString()
|
||||
return `https://api.atlassian.com/ex/jira/${params.cloudId}/rest/api/3/search/jql${qs ? `?${qs}` : ''}`
|
||||
}
|
||||
return 'https://api.atlassian.com/oauth/token/accessible-resources'
|
||||
},
|
||||
method: () => 'GET',
|
||||
headers: (params: JiraSearchIssuesParams) => {
|
||||
return {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
}
|
||||
},
|
||||
body: () => undefined as any,
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: JiraSearchIssuesParams) => {
|
||||
const performSearch = async (cloudId: string) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.jql) query.set('jql', params.jql)
|
||||
if (typeof params?.startAt === 'number') query.set('startAt', String(params.startAt))
|
||||
if (typeof params?.maxResults === 'number') query.set('maxResults', String(params.maxResults))
|
||||
if (Array.isArray(params?.fields) && params.fields.length > 0)
|
||||
query.set('fields', params.fields.join(','))
|
||||
const searchUrl = `https://api.atlassian.com/ex/jira/${cloudId}/rest/api/3/search/jql?${query.toString()}`
|
||||
const searchResponse = await fetch(searchUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${params!.accessToken}`,
|
||||
},
|
||||
})
|
||||
|
||||
if (!searchResponse.ok) {
|
||||
let message = `Failed to search Jira issues (${searchResponse.status})`
|
||||
try {
|
||||
const err = await searchResponse.json()
|
||||
message = err?.errorMessages?.join(', ') || err?.message || message
|
||||
} catch (_e) {}
|
||||
throw new Error(message)
|
||||
}
|
||||
|
||||
return searchResponse.json()
|
||||
}
|
||||
|
||||
let data: any
|
||||
|
||||
if (!params?.cloudId) {
|
||||
const cloudId = await getJiraCloudId(params!.domain, params!.accessToken)
|
||||
data = await performSearch(cloudId)
|
||||
} else {
|
||||
if (!response.ok) {
|
||||
let message = `Failed to search Jira issues (${response.status})`
|
||||
try {
|
||||
const err = await response.json()
|
||||
message = err?.errorMessages?.join(', ') || err?.message || message
|
||||
} catch (_e) {}
|
||||
throw new Error(message)
|
||||
}
|
||||
data = await response.json()
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
ts: new Date().toISOString(),
|
||||
total: data?.total ?? 0,
|
||||
startAt: data?.startAt ?? 0,
|
||||
maxResults: data?.maxResults ?? 0,
|
||||
issues: (data?.issues ?? []).map(transformSearchIssue),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
ts: TIMESTAMP_OUTPUT,
|
||||
total: { type: 'number', description: 'Total number of matching issues' },
|
||||
startAt: { type: 'number', description: 'Pagination start index' },
|
||||
maxResults: { type: 'number', description: 'Maximum results per page' },
|
||||
issues: {
|
||||
type: 'array',
|
||||
description: 'Array of matching issues',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: SEARCH_ISSUE_ITEM_PROPERTIES,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* V2 Search Issues Tool - Uses cursor-based pagination (nextPageToken) on /rest/api/3/search/jql.
|
||||
* The startAt parameter was deprecated on this endpoint as of Sept 2025.
|
||||
*/
|
||||
export const jiraSearchIssuesV2Tool: ToolConfig<
|
||||
JiraSearchIssuesV2Params,
|
||||
JiraSearchIssuesV2Response
|
||||
> = {
|
||||
id: 'jira_search_issues_v2',
|
||||
name: 'Jira Search Issues V2',
|
||||
description:
|
||||
'Search for Jira issues using JQL with cursor-based pagination (V2 - uses nextPageToken)',
|
||||
version: '2.0.0',
|
||||
|
||||
oauth: {
|
||||
required: true,
|
||||
provider: 'jira',
|
||||
},
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
@@ -287,7 +115,7 @@ export const jiraSearchIssuesV2Tool: ToolConfig<
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params: JiraSearchIssuesV2Params) => {
|
||||
url: (params: JiraSearchIssuesParams) => {
|
||||
if (params.cloudId) {
|
||||
const query = new URLSearchParams()
|
||||
if (params.jql) query.set('jql', params.jql)
|
||||
@@ -302,7 +130,7 @@ export const jiraSearchIssuesV2Tool: ToolConfig<
|
||||
return 'https://api.atlassian.com/oauth/token/accessible-resources'
|
||||
},
|
||||
method: () => 'GET',
|
||||
headers: (params: JiraSearchIssuesV2Params) => ({
|
||||
headers: (params: JiraSearchIssuesParams) => ({
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${params.accessToken}`,
|
||||
@@ -310,7 +138,7 @@ export const jiraSearchIssuesV2Tool: ToolConfig<
|
||||
body: () => undefined as any,
|
||||
},
|
||||
|
||||
transformResponse: async (response: Response, params?: JiraSearchIssuesV2Params) => {
|
||||
transformResponse: async (response: Response, params?: JiraSearchIssuesParams) => {
|
||||
const performSearch = async (cloudId: string) => {
|
||||
const query = new URLSearchParams()
|
||||
if (params?.jql) query.set('jql', params.jql)
|
||||
|
||||
@@ -873,7 +873,7 @@ export interface JiraRetrieveBulkParams {
|
||||
export interface JiraRetrieveResponseBulk extends ToolResponse {
|
||||
output: {
|
||||
ts: string
|
||||
total: number
|
||||
total: number | null
|
||||
issues: Array<{
|
||||
id: string
|
||||
key: string
|
||||
@@ -887,6 +887,8 @@ export interface JiraRetrieveResponseBulk extends ToolResponse {
|
||||
created: string
|
||||
updated: string
|
||||
}>
|
||||
nextPageToken: string | null
|
||||
isLast: boolean
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1034,7 +1036,7 @@ export interface JiraSearchIssuesParams {
|
||||
accessToken: string
|
||||
domain: string
|
||||
jql: string
|
||||
startAt?: number
|
||||
nextPageToken?: string
|
||||
maxResults?: number
|
||||
fields?: string[]
|
||||
cloudId?: string
|
||||
@@ -1043,9 +1045,6 @@ export interface JiraSearchIssuesParams {
|
||||
export interface JiraSearchIssuesResponse extends ToolResponse {
|
||||
output: {
|
||||
ts: string
|
||||
total: number
|
||||
startAt: number
|
||||
maxResults: number
|
||||
issues: Array<{
|
||||
id: string
|
||||
key: string
|
||||
@@ -1069,74 +1068,6 @@ export interface JiraSearchIssuesResponse extends ToolResponse {
|
||||
created: string
|
||||
updated: string
|
||||
}>
|
||||
}
|
||||
}
|
||||
|
||||
export interface JiraSearchIssuesV2Params {
|
||||
accessToken: string
|
||||
domain: string
|
||||
jql: string
|
||||
nextPageToken?: string
|
||||
maxResults?: number
|
||||
fields?: string[]
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface JiraSearchIssuesV2Response extends ToolResponse {
|
||||
output: {
|
||||
ts: string
|
||||
issues: Array<{
|
||||
id: string
|
||||
key: string
|
||||
self: string
|
||||
summary: string
|
||||
description: string | null
|
||||
status: {
|
||||
id: string
|
||||
name: string
|
||||
statusCategory?: { id: number; key: string; name: string; colorName: string }
|
||||
}
|
||||
issuetype: { id: string; name: string; subtask: boolean }
|
||||
project: { id: string; key: string; name: string }
|
||||
priority: { id: string; name: string } | null
|
||||
assignee: { accountId: string; displayName: string } | null
|
||||
reporter: { accountId: string; displayName: string } | null
|
||||
labels: string[]
|
||||
components: Array<{ id: string; name: string }>
|
||||
resolution: { id: string; name: string } | null
|
||||
duedate: string | null
|
||||
created: string
|
||||
updated: string
|
||||
}>
|
||||
nextPageToken: string | null
|
||||
isLast: boolean
|
||||
total: number | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface JiraRetrieveBulkV2Params {
|
||||
accessToken: string
|
||||
domain: string
|
||||
projectId: string
|
||||
cloudId?: string
|
||||
}
|
||||
|
||||
export interface JiraRetrieveResponseBulkV2 extends ToolResponse {
|
||||
output: {
|
||||
ts: string
|
||||
issues: Array<{
|
||||
id: string
|
||||
key: string
|
||||
self: string
|
||||
summary: string
|
||||
description: string | null
|
||||
status: { id: string; name: string }
|
||||
issuetype: { id: string; name: string }
|
||||
priority: { id: string; name: string } | null
|
||||
assignee: { accountId: string; displayName: string } | null
|
||||
created: string
|
||||
updated: string
|
||||
}>
|
||||
nextPageToken: string | null
|
||||
isLast: boolean
|
||||
total: number | null
|
||||
|
||||
@@ -15,17 +15,28 @@ export const createItemTool: ToolConfig<
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
vaultId: {
|
||||
type: 'string',
|
||||
@@ -62,39 +73,27 @@ export const createItemTool: ToolConfig<
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
return `${base}/v1/vaults/${params.vaultId}/items`
|
||||
},
|
||||
url: '/api/tools/onepassword/create-item',
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
vaultId: params.vaultId,
|
||||
category: params.category,
|
||||
title: params.title,
|
||||
tags: params.tags,
|
||||
fields: params.fields,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
vault: { id: params.vaultId },
|
||||
category: params.category,
|
||||
}
|
||||
|
||||
if (params.title) {
|
||||
body.title = params.title
|
||||
}
|
||||
|
||||
if (params.tags) {
|
||||
body.tags = params.tags.split(',').map((t) => t.trim())
|
||||
}
|
||||
|
||||
if (params.fields) {
|
||||
body.fields = JSON.parse(params.fields)
|
||||
}
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: transformFullItem({}), error: data.error }
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: transformFullItem(data),
|
||||
|
||||
@@ -14,17 +14,28 @@ export const deleteItemTool: ToolConfig<
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
vaultId: {
|
||||
type: 'string',
|
||||
@@ -41,17 +52,24 @@ export const deleteItemTool: ToolConfig<
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
return `${base}/v1/vaults/${params.vaultId}/items/${params.itemId}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
url: '/api/tools/onepassword/delete-item',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
vaultId: params.vaultId,
|
||||
itemId: params.itemId,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async () => {
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: { success: false }, error: data.error }
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
|
||||
@@ -12,17 +12,28 @@ export const getItemTool: ToolConfig<OnePasswordGetItemParams, OnePasswordGetIte
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
vaultId: {
|
||||
type: 'string',
|
||||
@@ -39,18 +50,24 @@ export const getItemTool: ToolConfig<OnePasswordGetItemParams, OnePasswordGetIte
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
return `${base}/v1/vaults/${params.vaultId}/items/${params.itemId}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
url: '/api/tools/onepassword/get-item',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
vaultId: params.vaultId,
|
||||
itemId: params.itemId,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: transformFullItem({}), error: data.error }
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: transformFullItem(data),
|
||||
|
||||
@@ -11,17 +11,28 @@ export const getVaultTool: ToolConfig<OnePasswordGetVaultParams, OnePasswordGetV
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
vaultId: {
|
||||
type: 'string',
|
||||
@@ -32,18 +43,37 @@ export const getVaultTool: ToolConfig<OnePasswordGetVaultParams, OnePasswordGetV
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
return `${base}/v1/vaults/${params.vaultId}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
url: '/api/tools/onepassword/get-vault',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
vaultId: params.vaultId,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return {
|
||||
success: false,
|
||||
output: {
|
||||
id: '',
|
||||
name: '',
|
||||
description: null,
|
||||
attributeVersion: 0,
|
||||
contentVersion: 0,
|
||||
items: 0,
|
||||
type: '',
|
||||
createdAt: null,
|
||||
updatedAt: null,
|
||||
},
|
||||
error: data.error,
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { getVaultTool } from '@/tools/onepassword/get_vault'
|
||||
import { listItemsTool } from '@/tools/onepassword/list_items'
|
||||
import { listVaultsTool } from '@/tools/onepassword/list_vaults'
|
||||
import { replaceItemTool } from '@/tools/onepassword/replace_item'
|
||||
import { resolveSecretTool } from '@/tools/onepassword/resolve_secret'
|
||||
import { updateItemTool } from '@/tools/onepassword/update_item'
|
||||
|
||||
export const onepasswordCreateItemTool = createItemTool
|
||||
@@ -14,4 +15,5 @@ export const onepasswordGetVaultTool = getVaultTool
|
||||
export const onepasswordListItemsTool = listItemsTool
|
||||
export const onepasswordListVaultsTool = listVaultsTool
|
||||
export const onepasswordReplaceItemTool = replaceItemTool
|
||||
export const onepasswordResolveSecretTool = resolveSecretTool
|
||||
export const onepasswordUpdateItemTool = updateItemTool
|
||||
|
||||
@@ -11,17 +11,28 @@ export const listItemsTool: ToolConfig<OnePasswordListItemsParams, OnePasswordLi
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
vaultId: {
|
||||
type: 'string',
|
||||
@@ -38,23 +49,29 @@ export const listItemsTool: ToolConfig<OnePasswordListItemsParams, OnePasswordLi
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
const query = params.filter ? `?filter=${encodeURIComponent(params.filter)}` : ''
|
||||
return `${base}/v1/vaults/${params.vaultId}/items${query}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
url: '/api/tools/onepassword/list-items',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
vaultId: params.vaultId,
|
||||
filter: params.filter,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: { items: [] }, error: data.error }
|
||||
}
|
||||
const items = Array.isArray(data) ? data : [data]
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
items: (data ?? []).map((item: any) => ({
|
||||
items: items.map((item: any) => ({
|
||||
id: item.id ?? null,
|
||||
title: item.title ?? null,
|
||||
vault: item.vault ?? null,
|
||||
|
||||
@@ -10,21 +10,32 @@ export const listVaultsTool: ToolConfig<
|
||||
> = {
|
||||
id: 'onepassword_list_vaults',
|
||||
name: '1Password List Vaults',
|
||||
description: 'List all vaults accessible by the Connect token',
|
||||
description: 'List all vaults accessible by the Connect token or Service Account',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
filter: {
|
||||
type: 'string',
|
||||
@@ -35,23 +46,28 @@ export const listVaultsTool: ToolConfig<
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
const query = params.filter ? `?filter=${encodeURIComponent(params.filter)}` : ''
|
||||
return `${base}/v1/vaults${query}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
url: '/api/tools/onepassword/list-vaults',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
filter: params.filter,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: { vaults: [] }, error: data.error }
|
||||
}
|
||||
const vaults = Array.isArray(data) ? data : [data]
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
vaults: (data ?? []).map((vault: any) => ({
|
||||
vaults: vaults.map((vault: any) => ({
|
||||
id: vault.id ?? null,
|
||||
name: vault.name ?? null,
|
||||
description: vault.description ?? null,
|
||||
|
||||
@@ -15,17 +15,28 @@ export const replaceItemTool: ToolConfig<
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
vaultId: {
|
||||
type: 'string',
|
||||
@@ -49,20 +60,25 @@ export const replaceItemTool: ToolConfig<
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
return `${base}/v1/vaults/${params.vaultId}/items/${params.itemId}`
|
||||
},
|
||||
method: 'PUT',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
url: '/api/tools/onepassword/replace-item',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
vaultId: params.vaultId,
|
||||
itemId: params.itemId,
|
||||
item: params.item,
|
||||
}),
|
||||
body: (params) => JSON.parse(params.item),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: transformFullItem({}), error: data.error }
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: transformFullItem(data),
|
||||
|
||||
67
apps/sim/tools/onepassword/resolve_secret.ts
Normal file
67
apps/sim/tools/onepassword/resolve_secret.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import type {
|
||||
OnePasswordResolveSecretParams,
|
||||
OnePasswordResolveSecretResponse,
|
||||
} from '@/tools/onepassword/types'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const resolveSecretTool: ToolConfig<
|
||||
OnePasswordResolveSecretParams,
|
||||
OnePasswordResolveSecretResponse
|
||||
> = {
|
||||
id: 'onepassword_resolve_secret',
|
||||
name: '1Password Resolve Secret',
|
||||
description:
|
||||
'Resolve a secret reference (op://vault/item/field) to its value. Service Account mode only.',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: must be "service_account" for this operation',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token',
|
||||
},
|
||||
secretReference: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description:
|
||||
'Secret reference URI (e.g., op://vault-name/item-name/field-name or op://vault-name/item-name/section-name/field-name)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: '/api/tools/onepassword/resolve-secret',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode ?? 'service_account',
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
secretReference: params.secretReference,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: { secret: '', reference: '' }, error: data.error }
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
secret: data.secret ?? '',
|
||||
reference: data.reference ?? '',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
secret: { type: 'string', description: 'The resolved secret value' },
|
||||
reference: { type: 'string', description: 'The original secret reference URI' },
|
||||
},
|
||||
}
|
||||
@@ -1,34 +1,32 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
export interface OnePasswordListVaultsParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
/** Base params shared by all 1Password tools (credential fields). */
|
||||
export interface OnePasswordBaseParams {
|
||||
connectionMode?: 'service_account' | 'connect'
|
||||
serviceAccountToken?: string
|
||||
apiKey?: string
|
||||
serverUrl?: string
|
||||
}
|
||||
|
||||
export interface OnePasswordListVaultsParams extends OnePasswordBaseParams {
|
||||
filter?: string
|
||||
}
|
||||
|
||||
export interface OnePasswordGetVaultParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
export interface OnePasswordGetVaultParams extends OnePasswordBaseParams {
|
||||
vaultId: string
|
||||
}
|
||||
|
||||
export interface OnePasswordListItemsParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
export interface OnePasswordListItemsParams extends OnePasswordBaseParams {
|
||||
vaultId: string
|
||||
filter?: string
|
||||
}
|
||||
|
||||
export interface OnePasswordGetItemParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
export interface OnePasswordGetItemParams extends OnePasswordBaseParams {
|
||||
vaultId: string
|
||||
itemId: string
|
||||
}
|
||||
|
||||
export interface OnePasswordCreateItemParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
export interface OnePasswordCreateItemParams extends OnePasswordBaseParams {
|
||||
vaultId: string
|
||||
category: string
|
||||
title?: string
|
||||
@@ -36,29 +34,27 @@ export interface OnePasswordCreateItemParams {
|
||||
fields?: string
|
||||
}
|
||||
|
||||
export interface OnePasswordUpdateItemParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
export interface OnePasswordUpdateItemParams extends OnePasswordBaseParams {
|
||||
vaultId: string
|
||||
itemId: string
|
||||
operations: string
|
||||
}
|
||||
|
||||
export interface OnePasswordReplaceItemParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
export interface OnePasswordReplaceItemParams extends OnePasswordBaseParams {
|
||||
vaultId: string
|
||||
itemId: string
|
||||
item: string
|
||||
}
|
||||
|
||||
export interface OnePasswordDeleteItemParams {
|
||||
apiKey: string
|
||||
serverUrl: string
|
||||
export interface OnePasswordDeleteItemParams extends OnePasswordBaseParams {
|
||||
vaultId: string
|
||||
itemId: string
|
||||
}
|
||||
|
||||
export interface OnePasswordResolveSecretParams extends OnePasswordBaseParams {
|
||||
secretReference: string
|
||||
}
|
||||
|
||||
export interface OnePasswordListVaultsResponse extends ToolResponse {
|
||||
output: {
|
||||
vaults: Array<{
|
||||
@@ -154,3 +150,10 @@ export interface OnePasswordDeleteItemResponse extends ToolResponse {
|
||||
success: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface OnePasswordResolveSecretResponse extends ToolResponse {
|
||||
output: {
|
||||
secret: string
|
||||
reference: string
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,17 +15,28 @@ export const updateItemTool: ToolConfig<
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
connectionMode: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
description: 'Connection mode: "service_account" or "connect"',
|
||||
},
|
||||
serviceAccountToken: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Service Account token (for Service Account mode)',
|
||||
},
|
||||
apiKey: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect API token',
|
||||
description: '1Password Connect API token (for Connect Server mode)',
|
||||
},
|
||||
serverUrl: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: '1Password Connect server URL (e.g., http://localhost:8080)',
|
||||
description: '1Password Connect server URL (for Connect Server mode)',
|
||||
},
|
||||
vaultId: {
|
||||
type: 'string',
|
||||
@@ -49,20 +60,25 @@ export const updateItemTool: ToolConfig<
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const base = params.serverUrl.replace(/\/$/, '')
|
||||
return `${base}/v1/vaults/${params.vaultId}/items/${params.itemId}`
|
||||
},
|
||||
method: 'PATCH',
|
||||
headers: (params) => ({
|
||||
Authorization: `Bearer ${params.apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
url: '/api/tools/onepassword/update-item',
|
||||
method: 'POST',
|
||||
headers: () => ({ 'Content-Type': 'application/json' }),
|
||||
body: (params) => ({
|
||||
connectionMode: params.connectionMode,
|
||||
serviceAccountToken: params.serviceAccountToken,
|
||||
serverUrl: params.serverUrl,
|
||||
apiKey: params.apiKey,
|
||||
vaultId: params.vaultId,
|
||||
itemId: params.itemId,
|
||||
operations: params.operations,
|
||||
}),
|
||||
body: (params) => JSON.parse(params.operations),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
const data = await response.json()
|
||||
if (data.error) {
|
||||
return { success: false, output: transformFullItem({}), error: data.error }
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
output: transformFullItem(data),
|
||||
|
||||
@@ -814,7 +814,6 @@ import {
|
||||
jiraAddWorklogTool,
|
||||
jiraAssignIssueTool,
|
||||
jiraBulkRetrieveTool,
|
||||
jiraBulkRetrieveV2Tool,
|
||||
jiraCreateIssueLinkTool,
|
||||
jiraDeleteAttachmentTool,
|
||||
jiraDeleteCommentTool,
|
||||
@@ -828,7 +827,6 @@ import {
|
||||
jiraRemoveWatcherTool,
|
||||
jiraRetrieveTool,
|
||||
jiraSearchIssuesTool,
|
||||
jiraSearchIssuesV2Tool,
|
||||
jiraTransitionIssueTool,
|
||||
jiraUpdateCommentTool,
|
||||
jiraUpdateTool,
|
||||
@@ -1169,6 +1167,7 @@ import {
|
||||
onepasswordListItemsTool,
|
||||
onepasswordListVaultsTool,
|
||||
onepasswordReplaceItemTool,
|
||||
onepasswordResolveSecretTool,
|
||||
onepasswordUpdateItemTool,
|
||||
} from '@/tools/onepassword'
|
||||
import { openAIEmbeddingsTool, openAIImageTool } from '@/tools/openai'
|
||||
@@ -1936,12 +1935,10 @@ export const tools: Record<string, ToolConfig> = {
|
||||
jira_update: jiraUpdateTool,
|
||||
jira_write: jiraWriteTool,
|
||||
jira_bulk_read: jiraBulkRetrieveTool,
|
||||
jira_bulk_read_v2: jiraBulkRetrieveV2Tool,
|
||||
jira_delete_issue: jiraDeleteIssueTool,
|
||||
jira_assign_issue: jiraAssignIssueTool,
|
||||
jira_transition_issue: jiraTransitionIssueTool,
|
||||
jira_search_issues: jiraSearchIssuesTool,
|
||||
jira_search_issues_v2: jiraSearchIssuesV2Tool,
|
||||
jira_add_comment: jiraAddCommentTool,
|
||||
jira_get_comments: jiraGetCommentsTool,
|
||||
jira_update_comment: jiraUpdateCommentTool,
|
||||
@@ -2157,6 +2154,7 @@ export const tools: Record<string, ToolConfig> = {
|
||||
onepassword_replace_item: onepasswordReplaceItemTool,
|
||||
onepassword_update_item: onepasswordUpdateItemTool,
|
||||
onepassword_delete_item: onepasswordDeleteItemTool,
|
||||
onepassword_resolve_secret: onepasswordResolveSecretTool,
|
||||
gmail_send: gmailSendTool,
|
||||
gmail_send_v2: gmailSendV2Tool,
|
||||
gmail_read: gmailReadTool,
|
||||
|
||||
5
bun.lock
5
bun.lock
@@ -54,6 +54,7 @@
|
||||
"name": "sim",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@1password/sdk": "0.3.1",
|
||||
"@a2a-js/sdk": "0.3.7",
|
||||
"@anthropic-ai/sdk": "0.71.2",
|
||||
"@aws-sdk/client-bedrock-runtime": "3.940.0",
|
||||
@@ -326,6 +327,10 @@
|
||||
"react-dom": "19.2.1",
|
||||
},
|
||||
"packages": {
|
||||
"@1password/sdk": ["@1password/sdk@0.3.1", "", { "dependencies": { "@1password/sdk-core": "0.3.1" } }, "sha512-20zbQfqsjcECT0gvnAw4zONJDt3XQgNH946pZR0NV1Qxukyaz/DKB0cBnBNCCEWZg93Bah8poaR6gJCyuNX14w=="],
|
||||
|
||||
"@1password/sdk-core": ["@1password/sdk-core@0.3.1", "", {}, "sha512-zFkbRznmE47kpke10OpO/9R0AF5csNWS+naFbadgXuFX1LlxY+2C28NSKbCXhLTqmcuWifBfPdZQ728GJ1i5xg=="],
|
||||
|
||||
"@a2a-js/sdk": ["@a2a-js/sdk@0.3.7", "", { "dependencies": { "uuid": "^11.1.0" }, "peerDependencies": { "express": "^4.21.2 || ^5.1.0" }, "optionalPeers": ["express"] }, "sha512-1WBghkOjgiKt4rPNje8jlB9VateVQXqyjlc887bY/H8yM82Hlf0+5JW8zB98BPExKAplI5XqtXVH980J6vqi+w=="],
|
||||
|
||||
"@adobe/css-tools": ["@adobe/css-tools@4.4.4", "", {}, "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg=="],
|
||||
|
||||
Reference in New Issue
Block a user