Skip to content

Commit d7f7af8

Browse files
authored
[dev] [Carhartlewis] lewis/comp-jumpcloud-integration (#1941)
* feat(jumpcloud): add integration for syncing employees from JumpCloud * fix(jumpcloud): added rippling back as a valid provider * fix(jumpcloud): updated help text * fix(sync): normalize email to lowercase for consistent database operations * chore(deps): update package versions and bun.lock for consistency
1 parent 3a53acc commit d7f7af8

File tree

15 files changed

+1121
-54
lines changed

15 files changed

+1121
-54
lines changed

apps/api/src/integration-platform/controllers/sync.controller.ts

Lines changed: 514 additions & 12 deletions
Large diffs are not rendered by default.

apps/api/src/trigger/integration-platform/sync-employees-schedule.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ async function syncProvider(params: SyncProviderParams): Promise<SyncResult> {
194194
case 'rippling':
195195
return syncRippling({ connectionId, organizationId });
196196

197+
case 'jumpcloud':
198+
return syncJumpCloud({ connectionId, organizationId });
199+
197200
default:
198201
throw new Error(`No sync handler for provider: ${providerSlug}`);
199202
}
@@ -272,3 +275,39 @@ async function syncRippling({
272275
errors: data.errors || 0,
273276
};
274277
}
278+
279+
async function syncJumpCloud({
280+
connectionId,
281+
organizationId,
282+
}: {
283+
connectionId: string;
284+
organizationId: string;
285+
}): Promise<SyncResult> {
286+
const url = new URL(
287+
`${API_BASE_URL}/v1/integrations/sync/jumpcloud/employees`,
288+
);
289+
url.searchParams.set('organizationId', organizationId);
290+
url.searchParams.set('connectionId', connectionId);
291+
292+
const response = await fetch(url.toString(), {
293+
method: 'POST',
294+
headers: {
295+
'Content-Type': 'application/json',
296+
},
297+
});
298+
299+
if (!response.ok) {
300+
const errorBody = await response.text();
301+
throw new Error(`JumpCloud sync failed: ${response.status} - ${errorBody}`);
302+
}
303+
304+
const data = await response.json();
305+
return {
306+
success: data.success,
307+
imported: data.imported || 0,
308+
reactivated: data.reactivated || 0,
309+
deactivated: data.deactivated || 0,
310+
skipped: data.skipped || 0,
311+
errors: data.errors || 0,
312+
};
313+
}

apps/app/src/app/(app)/[orgId]/people/all/components/TeamMembersClient.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ import type { MemberWithUser, TeamMembersData } from './TeamMembers';
2323
import type { removeMember } from '../actions/removeMember';
2424
import type { revokeInvitation } from '../actions/revokeInvitation';
2525

26+
import { usePeopleActions } from '@/hooks/use-people-api';
2627
import type { EmployeeSyncConnectionsData } from '../data/queries';
2728
import { useEmployeeSync } from '../hooks/useEmployeeSync';
2829
import { InviteMembersModal } from './InviteMembersModal';
29-
import { usePeopleActions } from '@/hooks/use-people-api';
3030

3131
// Define prop types using typeof for the actions still used
3232
interface TeamMembersClientProps {
@@ -74,6 +74,7 @@ export function TeamMembersClient({
7474
const {
7575
googleWorkspaceConnectionId,
7676
ripplingConnectionId,
77+
jumpcloudConnectionId,
7778
selectedProvider,
7879
isSyncing,
7980
syncEmployees,
@@ -85,7 +86,7 @@ export function TeamMembersClient({
8586
const lastSyncAt = employeeSyncData.lastSyncAt;
8687
const nextSyncAt = employeeSyncData.nextSyncAt;
8788

88-
const handleEmployeeSync = async (provider: 'google-workspace' | 'rippling') => {
89+
const handleEmployeeSync = async (provider: 'google-workspace' | 'rippling' | 'jumpcloud') => {
8990
const result = await syncEmployees(provider);
9091
if (result?.success) {
9192
router.refresh();
@@ -383,6 +384,24 @@ export function TeamMembersClient({
383384
</div>
384385
</SelectItem>
385386
)}
387+
{jumpcloudConnectionId && (
388+
<SelectItem value="jumpcloud">
389+
<div className="flex items-center gap-2">
390+
<Image
391+
src={getProviderLogo('jumpcloud')}
392+
alt="JumpCloud"
393+
width={16}
394+
height={16}
395+
className="rounded-sm"
396+
unoptimized
397+
/>
398+
JumpCloud
399+
{selectedProvider === 'jumpcloud' && (
400+
<span className="ml-auto text-xs text-muted-foreground">Active</span>
401+
)}
402+
</div>
403+
</SelectItem>
404+
)}
386405
</SelectContent>
387406
</Select>
388407
</div>

apps/app/src/app/(app)/[orgId]/people/all/data/queries.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { serverApi } from '@/lib/server-api-client';
33
export interface EmployeeSyncConnectionsData {
44
googleWorkspaceConnectionId: string | null;
55
ripplingConnectionId: string | null;
6-
selectedProvider: 'google-workspace' | 'rippling' | null | undefined;
6+
jumpcloudConnectionId: string | null;
7+
selectedProvider: 'google-workspace' | 'rippling' | 'jumpcloud' | null | undefined;
78
lastSyncAt: Date | null;
89
nextSyncAt: Date | null;
910
}
@@ -18,14 +19,17 @@ interface ConnectionStatus {
1819
export async function getEmployeeSyncConnections(
1920
organizationId: string,
2021
): Promise<EmployeeSyncConnectionsData> {
21-
const [gwResponse, ripplingResponse, providerResponse] = await Promise.all([
22+
const [gwResponse, ripplingResponse, jumpcloudResponse, providerResponse] = await Promise.all([
2223
serverApi.post<ConnectionStatus>(
2324
`/v1/integrations/sync/google-workspace/status?organizationId=${organizationId}`,
2425
),
2526
serverApi.post<ConnectionStatus>(
2627
`/v1/integrations/sync/rippling/status?organizationId=${organizationId}`,
2728
),
28-
serverApi.get<{ provider: 'google-workspace' | 'rippling' | null }>(
29+
serverApi.post<ConnectionStatus>(
30+
`/v1/integrations/sync/jumpcloud/status?organizationId=${organizationId}`,
31+
),
32+
serverApi.get<{ provider: 'google-workspace' | 'rippling' | 'jumpcloud' | null }>(
2933
`/v1/integrations/sync/employee-sync-provider?organizationId=${organizationId}`,
3034
),
3135
]);
@@ -37,7 +41,9 @@ export async function getEmployeeSyncConnections(
3741
? gwResponse.data
3842
: selectedProviderSlug === 'rippling'
3943
? ripplingResponse.data
40-
: null;
44+
: selectedProviderSlug === 'jumpcloud'
45+
? jumpcloudResponse.data
46+
: null;
4147

4248
return {
4349
googleWorkspaceConnectionId:
@@ -48,6 +54,10 @@ export async function getEmployeeSyncConnections(
4854
ripplingResponse.data?.connected && ripplingResponse.data.connectionId
4955
? ripplingResponse.data.connectionId
5056
: null,
57+
jumpcloudConnectionId:
58+
jumpcloudResponse.data?.connected && jumpcloudResponse.data.connectionId
59+
? jumpcloudResponse.data.connectionId
60+
: null,
5161
selectedProvider: selectedProviderSlug,
5262
lastSyncAt: selectedConnection?.lastSyncAt ? new Date(selectedConnection.lastSyncAt) : null,
5363
nextSyncAt: selectedConnection?.nextSyncAt ? new Date(selectedConnection.nextSyncAt) : null,

apps/app/src/app/(app)/[orgId]/people/all/hooks/useEmployeeSync.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import useSWR from 'swr';
77

88
import type { EmployeeSyncConnectionsData } from '../data/queries';
99

10-
type SyncProvider = 'google-workspace' | 'rippling';
10+
type SyncProvider = 'google-workspace' | 'rippling' | 'jumpcloud';
1111

1212
interface SyncResult {
1313
success: boolean;
@@ -27,6 +27,7 @@ interface UseEmployeeSyncOptions {
2727
interface UseEmployeeSyncReturn {
2828
googleWorkspaceConnectionId: string | null;
2929
ripplingConnectionId: string | null;
30+
jumpcloudConnectionId: string | null;
3031
selectedProvider: SyncProvider | null;
3132
isSyncing: boolean;
3233
syncEmployees: (provider: SyncProvider) => Promise<SyncResult | null>;
@@ -47,6 +48,11 @@ const PROVIDER_CONFIG = {
4748
shortName: 'Rippling',
4849
logo: 'https://img.logo.dev/rippling.com?token=pk_AZatYxV5QDSfWpRDaBxzRQ&format=png&retina=true',
4950
},
51+
jumpcloud: {
52+
name: 'JumpCloud',
53+
shortName: 'JumpCloud',
54+
logo: 'https://img.logo.dev/jumpcloud.com?token=pk_AZatYxV5QDSfWpRDaBxzRQ&format=png&retina=true',
55+
},
5056
} as const;
5157

5258
export const useEmployeeSync = ({
@@ -63,6 +69,7 @@ export const useEmployeeSync = ({
6369

6470
const googleWorkspaceConnectionId = data?.googleWorkspaceConnectionId ?? null;
6571
const ripplingConnectionId = data?.ripplingConnectionId ?? null;
72+
const jumpcloudConnectionId = data?.jumpcloudConnectionId ?? null;
6673
const selectedProvider = data?.selectedProvider ?? null;
6774

6875
const setSyncProvider = async (provider: SyncProvider | null) => {
@@ -86,7 +93,11 @@ export const useEmployeeSync = ({
8693

8794
const syncEmployees = async (provider: SyncProvider): Promise<SyncResult | null> => {
8895
const connectionId =
89-
provider === 'google-workspace' ? googleWorkspaceConnectionId : ripplingConnectionId;
96+
provider === 'google-workspace'
97+
? googleWorkspaceConnectionId
98+
: provider === 'rippling'
99+
? ripplingConnectionId
100+
: jumpcloudConnectionId;
90101

91102
if (!connectionId) {
92103
toast.error(`${PROVIDER_CONFIG[provider].name} is not connected`);
@@ -149,11 +160,16 @@ export const useEmployeeSync = ({
149160
return {
150161
googleWorkspaceConnectionId,
151162
ripplingConnectionId,
163+
jumpcloudConnectionId,
152164
selectedProvider,
153165
isSyncing,
154166
syncEmployees,
155167
setSyncProvider,
156-
hasAnyConnection: !!(googleWorkspaceConnectionId || ripplingConnectionId),
168+
hasAnyConnection: !!(
169+
googleWorkspaceConnectionId ||
170+
ripplingConnectionId ||
171+
jumpcloudConnectionId
172+
),
157173
getProviderName,
158174
getProviderLogo,
159175
};

bun.lock

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@
604604

605605
"@ai-sdk/deepseek": ["@ai-sdk/deepseek@1.0.32", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-DDNZSZn6OuExVBJBAWdk3VeyQPH+pYwSykixePhzll9EnT3aakapMYr5gjw3wMl+eZ0tLplythHL1TfIehUZ0g=="],
606606

607-
"@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA=="],
607+
"@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.22", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-6fHjDfCbjfj4vyMExuLei7ir2///E5sNwNZaobdJsJIxJjDSsjzSLGO/aUI7p9eOnB8XctDrDSF5ilwDGpi6eg=="],
608608

609609
"@ai-sdk/google": ["@ai-sdk/google@2.0.47", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-grIlvzh+jzMoKNOnn5Xe/8fdYiJOs0ThMVetsGzqflvMkUNF3B83t5i0kf4XqiM8MwTJ8gkdOA4VeQOZKR7TkA=="],
610610

@@ -2568,7 +2568,7 @@
25682568

25692569
"aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
25702570

2571-
"ai": ["ai@5.0.113", "", { "dependencies": { "@ai-sdk/gateway": "2.0.21", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-26vivpSO/mzZj0k1Si2IpsFspp26ttQICHRySQiMrtWcRd5mnJMX2a8sG28vmZ38C+JUn1cWmfZrsLMxkSMw9g=="],
2571+
"ai": ["ai@5.0.115", "", { "dependencies": { "@ai-sdk/gateway": "2.0.22", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-aVuHx0orGxXvhyL7oXUyW8TnWQE6Al8f3Bl6VZjz0WHMV+WaACHPkSyvQ3wje2QCUGzdl5DBF5d+OaXyghPQyg=="],
25722572

25732573
"ai-elements": ["ai-elements@1.6.3", "", { "bin": { "elements": "index.js" } }, "sha512-M0A5NrUqCMV2w9hJV+kOuFi+XKo1BjlawheaqfrG+jovWsyXyCalOOH2dM4w/BwjABwje5yZX5MnMIUwnFmqzg=="],
25742574

@@ -5744,6 +5744,10 @@
57445744

57455745
"@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="],
57465746

5747+
"@ai-sdk/react/ai": ["ai@5.0.113", "", { "dependencies": { "@ai-sdk/gateway": "2.0.21", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-26vivpSO/mzZj0k1Si2IpsFspp26ttQICHRySQiMrtWcRd5mnJMX2a8sG28vmZ38C+JUn1cWmfZrsLMxkSMw9g=="],
5748+
5749+
"@ai-sdk/rsc/ai": ["ai@5.0.113", "", { "dependencies": { "@ai-sdk/gateway": "2.0.21", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-26vivpSO/mzZj0k1Si2IpsFspp26ttQICHRySQiMrtWcRd5mnJMX2a8sG28vmZ38C+JUn1cWmfZrsLMxkSMw9g=="],
5750+
57475751
"@angular-devkit/core/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
57485752

57495753
"@angular-devkit/core/picomatch": ["picomatch@4.0.2", "", {}, "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg=="],
@@ -5790,6 +5794,8 @@
57905794

57915795
"@browserbasehq/sdk/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="],
57925796

5797+
"@browserbasehq/stagehand/ai": ["ai@5.0.113", "", { "dependencies": { "@ai-sdk/gateway": "2.0.21", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-26vivpSO/mzZj0k1Si2IpsFspp26ttQICHRySQiMrtWcRd5mnJMX2a8sG28vmZ38C+JUn1cWmfZrsLMxkSMw9g=="],
5798+
57935799
"@browserbasehq/stagehand/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
57945800

57955801
"@browserbasehq/stagehand/puppeteer-core": ["puppeteer-core@22.15.0", "", { "dependencies": { "@puppeteer/browsers": "2.3.0", "chromium-bidi": "0.6.3", "debug": "^4.3.6", "devtools-protocol": "0.0.1312386", "ws": "^8.18.0" } }, "sha512-cHArnywCiAAVXa3t4GGL2vttNxh7GqXtIYGym99egkNJ3oG//wL9LkvO4WE8W1TJe95t1F1ocu9X4xWaGsOKOA=="],
@@ -6978,6 +6984,10 @@
69786984

69796985
"zod-error/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
69806986

6987+
"@ai-sdk/react/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA=="],
6988+
6989+
"@ai-sdk/rsc/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA=="],
6990+
69816991
"@angular-devkit/core/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
69826992

69836993
"@angular-devkit/schematics/ora/cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
@@ -7004,6 +7014,8 @@
70047014

70057015
"@browserbasehq/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
70067016

7017+
"@browserbasehq/stagehand/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.21", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.19", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA=="],
7018+
70077019
"@browserbasehq/stagehand/puppeteer-core/@puppeteer/browsers": ["@puppeteer/browsers@2.3.0", "", { "dependencies": { "debug": "^4.3.5", "extract-zip": "^2.0.1", "progress": "^2.0.3", "proxy-agent": "^6.4.0", "semver": "^7.6.3", "tar-fs": "^3.0.6", "unbzip2-stream": "^1.4.3", "yargs": "^17.7.2" }, "bin": { "browsers": "lib/cjs/main-cli.js" } }, "sha512-ioXoq9gPxkss4MYhD+SFaU9p1IHFUX0ILAWFPyjGaBdjLsYAlZw6j1iLA0N/m12uVHLFDfSYNF7EQccjinIMDA=="],
70087020

70097021
"@browserbasehq/stagehand/puppeteer-core/chromium-bidi": ["chromium-bidi@0.6.3", "", { "dependencies": { "mitt": "3.0.1", "urlpattern-polyfill": "10.0.0", "zod": "3.23.8" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-qXlsCmpCZJAnoTYI83Iu6EdYQpMYdVkCfq08KDh2pmlVqK5t5IA9mGs4/LwCwp4fqisSOMXZxP3HIh8w8aRn0A=="],
@@ -7594,6 +7606,10 @@
75947606

75957607
"wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
75967608

7609+
"@ai-sdk/react/ai/@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="],
7610+
7611+
"@ai-sdk/rsc/ai/@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="],
7612+
75977613
"@angular-devkit/schematics/ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="],
75987614

75997615
"@angular-devkit/schematics/ora/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
@@ -7604,6 +7620,8 @@
76047620

76057621
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
76067622

7623+
"@browserbasehq/stagehand/ai/@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="],
7624+
76077625
"@browserbasehq/stagehand/puppeteer-core/chromium-bidi/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="],
76087626

76097627
"@calcom/atoms/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],

0 commit comments

Comments
 (0)