mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 15:07:55 -05:00
v0.5.45: light mode fixes, realtime usage indicator, docker build improvements
This commit is contained in:
19
.github/workflows/test-build.yml
vendored
19
.github/workflows/test-build.yml
vendored
@@ -23,16 +23,17 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: latest
|
node-version: latest
|
||||||
|
|
||||||
- name: Cache Bun dependencies
|
- name: Mount Bun cache (Sticky Disk)
|
||||||
uses: actions/cache@v4
|
uses: useblacksmith/stickydisk@v1
|
||||||
with:
|
with:
|
||||||
path: |
|
key: ${{ github.repository }}-bun-cache
|
||||||
~/.bun/install/cache
|
path: ~/.bun/install/cache
|
||||||
node_modules
|
|
||||||
**/node_modules
|
- name: Mount node_modules (Sticky Disk)
|
||||||
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
|
uses: useblacksmith/stickydisk@v1
|
||||||
restore-keys: |
|
with:
|
||||||
${{ runner.os }}-bun-
|
key: ${{ github.repository }}-node-modules
|
||||||
|
path: ./node_modules
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: bun install --frozen-lockfile
|
run: bun install --frozen-lockfile
|
||||||
|
|||||||
@@ -391,6 +391,17 @@
|
|||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subblock divider visibility
|
||||||
|
* Hides dividers when adjacent subblocks render empty content (e.g., schedule-info without data).
|
||||||
|
* Uses CSS :has() to detect empty .subblock-content elements and hide associated dividers.
|
||||||
|
* Selectors ordered by ascending specificity: (0,4,0) then (0,5,0)
|
||||||
|
*/
|
||||||
|
.subblock-row:has(> .subblock-content:empty) > .subblock-divider,
|
||||||
|
.subblock-row:has(+ .subblock-row > .subblock-content:empty) > .subblock-divider {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dark mode specific overrides
|
* Dark mode specific overrides
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,7 +3,15 @@
|
|||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import { createLogger } from '@sim/logger'
|
import { createLogger } from '@sim/logger'
|
||||||
import { Check } from 'lucide-react'
|
import { Check } from 'lucide-react'
|
||||||
import { Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from '@/components/emcn'
|
import {
|
||||||
|
Badge,
|
||||||
|
Button,
|
||||||
|
Modal,
|
||||||
|
ModalBody,
|
||||||
|
ModalContent,
|
||||||
|
ModalFooter,
|
||||||
|
ModalHeader,
|
||||||
|
} from '@/components/emcn'
|
||||||
import { client } from '@/lib/auth/auth-client'
|
import { client } from '@/lib/auth/auth-client'
|
||||||
import {
|
import {
|
||||||
getProviderIdFromServiceId,
|
getProviderIdFromServiceId,
|
||||||
@@ -407,9 +415,9 @@ export function OAuthRequiredModal({
|
|||||||
<div className='flex flex-1 items-center gap-[8px] text-[12px] text-[var(--text-primary)]'>
|
<div className='flex flex-1 items-center gap-[8px] text-[12px] text-[var(--text-primary)]'>
|
||||||
<span>{getScopeDescription(scope)}</span>
|
<span>{getScopeDescription(scope)}</span>
|
||||||
{newScopesSet.has(scope) && (
|
{newScopesSet.has(scope) && (
|
||||||
<span className='inline-flex items-center gap-[6px] rounded-[6px] bg-[#fde68a] px-[7px] py-[1px] font-medium text-[#a16207] text-[11px] dark:bg-[rgba(245,158,11,0.2)] dark:text-[#fcd34d]'>
|
<Badge variant='amber' size='sm'>
|
||||||
New
|
New
|
||||||
</span>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ export function CredentialSelector({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<Combobox
|
<Combobox
|
||||||
options={comboboxOptions}
|
options={comboboxOptions}
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
@@ -247,9 +247,20 @@ export function CredentialSelector({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{needsUpdate && (
|
{needsUpdate && (
|
||||||
<div className='mt-2 flex items-center justify-between rounded-[6px] border border-amber-300/40 bg-amber-50/60 px-2 py-1 font-medium text-[12px] transition-colors dark:bg-amber-950/10'>
|
<div className='mt-[8px] flex flex-col gap-[4px] rounded-[4px] border bg-[var(--surface-2)] px-[8px] py-[6px]'>
|
||||||
<span>Additional permissions required</span>
|
<div className='flex items-center font-medium text-[12px]'>
|
||||||
{!isForeign && <Button onClick={() => setShowOAuthModal(true)}>Update access</Button>}
|
<span className='mr-[6px] inline-block h-[6px] w-[6px] rounded-[2px] bg-amber-500' />
|
||||||
|
Additional permissions required
|
||||||
|
</div>
|
||||||
|
{!isForeign && (
|
||||||
|
<Button
|
||||||
|
variant='active'
|
||||||
|
onClick={() => setShowOAuthModal(true)}
|
||||||
|
className='w-full px-[8px] py-[4px] font-medium text-[12px]'
|
||||||
|
>
|
||||||
|
Update access
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -264,7 +275,7 @@ export function CredentialSelector({
|
|||||||
serviceId={serviceId}
|
serviceId={serviceId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -537,7 +537,7 @@ export function McpDynamicArgs({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative space-y-4'>
|
<div className='relative'>
|
||||||
{/* Hidden dummy inputs to prevent browser password manager autofill */}
|
{/* Hidden dummy inputs to prevent browser password manager autofill */}
|
||||||
<input
|
<input
|
||||||
type='text'
|
type='text'
|
||||||
@@ -563,6 +563,7 @@ export function McpDynamicArgs({
|
|||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
|
<div className='space-y-4'>
|
||||||
{toolSchema.properties &&
|
{toolSchema.properties &&
|
||||||
Object.entries(toolSchema.properties).map(([paramName, paramSchema]) => {
|
Object.entries(toolSchema.properties).map(([paramName, paramSchema]) => {
|
||||||
const inputType = getInputType(paramSchema as any)
|
const inputType = getInputType(paramSchema as any)
|
||||||
@@ -586,5 +587,6 @@ export function McpDynamicArgs({
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ export function ToolCredentialSelector({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
<Combobox
|
<Combobox
|
||||||
options={comboboxOptions}
|
options={comboboxOptions}
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
@@ -217,9 +217,20 @@ export function ToolCredentialSelector({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{needsUpdate && (
|
{needsUpdate && (
|
||||||
<div className='mt-2 flex items-center justify-between rounded-[6px] border border-amber-300/40 bg-amber-50/60 px-2 py-1 font-medium text-[12px] transition-colors dark:bg-amber-950/10'>
|
<div className='mt-[8px] flex flex-col gap-[4px] rounded-[4px] border bg-[var(--surface-2)] px-[8px] py-[6px]'>
|
||||||
<span>Additional permissions required</span>
|
<div className='flex items-center font-medium text-[12px]'>
|
||||||
{!isForeign && <Button onClick={() => setShowOAuthModal(true)}>Update access</Button>}
|
<span className='mr-[6px] inline-block h-[6px] w-[6px] rounded-[2px] bg-amber-500' />
|
||||||
|
Additional permissions required
|
||||||
|
</div>
|
||||||
|
{!isForeign && (
|
||||||
|
<Button
|
||||||
|
variant='active'
|
||||||
|
onClick={() => setShowOAuthModal(true)}
|
||||||
|
className='w-full px-[8px] py-[4px] font-medium text-[12px]'
|
||||||
|
>
|
||||||
|
Update access
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -234,7 +245,7 @@ export function ToolCredentialSelector({
|
|||||||
serviceId={serviceId}
|
serviceId={serviceId}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -866,7 +866,7 @@ function SubBlockComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onMouseDown={handleMouseDown} className='flex flex-col gap-[10px]'>
|
<div onMouseDown={handleMouseDown} className='subblock-content flex flex-col gap-[10px]'>
|
||||||
{renderLabel(
|
{renderLabel(
|
||||||
config,
|
config,
|
||||||
isValidJson,
|
isValidJson,
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ export function Editor() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={stableKey}>
|
<div key={stableKey} className='subblock-row'>
|
||||||
<SubBlock
|
<SubBlock
|
||||||
blockId={currentBlockId}
|
blockId={currentBlockId}
|
||||||
config={subBlock}
|
config={subBlock}
|
||||||
@@ -352,7 +352,7 @@ export function Editor() {
|
|||||||
allowExpandInPreview={false}
|
allowExpandInPreview={false}
|
||||||
/>
|
/>
|
||||||
{index < subBlocks.length - 1 && (
|
{index < subBlocks.length - 1 && (
|
||||||
<div className='px-[2px] pt-[16px] pb-[13px]'>
|
<div className='subblock-divider px-[2px] pt-[16px] pb-[13px]'>
|
||||||
<div
|
<div
|
||||||
className='h-[1.25px]'
|
className='h-[1.25px]'
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ export function useWand({
|
|||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
|
queryClient.invalidateQueries({ queryKey: subscriptionKeys.all })
|
||||||
}, 1000)
|
}, 1000)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error.name === 'AbortError') {
|
if (error.name === 'AbortError') {
|
||||||
|
|||||||
@@ -573,7 +573,7 @@ export function useWorkflowExecution() {
|
|||||||
|
|
||||||
// Invalidate subscription queries to update usage
|
// Invalidate subscription queries to update usage
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
|
queryClient.invalidateQueries({ queryKey: subscriptionKeys.all })
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
||||||
safeEnqueue(encodeSSE({ event: 'final', data: result }))
|
safeEnqueue(encodeSSE({ event: 'final', data: result }))
|
||||||
@@ -646,7 +646,7 @@ export function useWorkflowExecution() {
|
|||||||
|
|
||||||
// Invalidate subscription queries to update usage
|
// Invalidate subscription queries to update usage
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
|
queryClient.invalidateQueries({ queryKey: subscriptionKeys.all })
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export function CancelSubscription({ subscription, subscriptionData }: CancelSub
|
|||||||
logger.info('Subscription restored successfully', result)
|
logger.info('Subscription restored successfully', result)
|
||||||
}
|
}
|
||||||
|
|
||||||
await queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
|
await queryClient.invalidateQueries({ queryKey: subscriptionKeys.all })
|
||||||
if (activeOrgId) {
|
if (activeOrgId) {
|
||||||
await queryClient.invalidateQueries({ queryKey: organizationKeys.detail(activeOrgId) })
|
await queryClient.invalidateQueries({ queryKey: organizationKeys.detail(activeOrgId) })
|
||||||
await queryClient.invalidateQueries({ queryKey: organizationKeys.billing(activeOrgId) })
|
await queryClient.invalidateQueries({ queryKey: organizationKeys.billing(activeOrgId) })
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ export function UsageIndicator({ onClick }: UsageIndicatorProps) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleOperationConfirmed = () => {
|
const handleOperationConfirmed = () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
|
queryClient.invalidateQueries({ queryKey: subscriptionKeys.all })
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
onOperationConfirmed(handleOperationConfirmed)
|
onOperationConfirmed(handleOperationConfirmed)
|
||||||
|
|||||||
@@ -98,13 +98,13 @@ export function useUpdateUsageLimit() {
|
|||||||
return response.json()
|
return response.json()
|
||||||
},
|
},
|
||||||
onMutate: async ({ limit }) => {
|
onMutate: async ({ limit }) => {
|
||||||
await queryClient.cancelQueries({ queryKey: subscriptionKeys.user() })
|
await queryClient.cancelQueries({ queryKey: subscriptionKeys.all })
|
||||||
await queryClient.cancelQueries({ queryKey: subscriptionKeys.usage() })
|
|
||||||
|
|
||||||
const previousSubscriptionData = queryClient.getQueryData(subscriptionKeys.user())
|
const previousSubscriptionData = queryClient.getQueryData(subscriptionKeys.user(false))
|
||||||
|
const previousSubscriptionDataWithOrg = queryClient.getQueryData(subscriptionKeys.user(true))
|
||||||
const previousUsageData = queryClient.getQueryData(subscriptionKeys.usage())
|
const previousUsageData = queryClient.getQueryData(subscriptionKeys.usage())
|
||||||
|
|
||||||
queryClient.setQueryData(subscriptionKeys.user(), (old: any) => {
|
const updateSubscriptionData = (old: any) => {
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
const currentUsage = old.data?.usage?.current || 0
|
const currentUsage = old.data?.usage?.current || 0
|
||||||
const newPercentUsed = limit > 0 ? (currentUsage / limit) * 100 : 0
|
const newPercentUsed = limit > 0 ? (currentUsage / limit) * 100 : 0
|
||||||
@@ -120,7 +120,10 @@ export function useUpdateUsageLimit() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
queryClient.setQueryData(subscriptionKeys.user(false), updateSubscriptionData)
|
||||||
|
queryClient.setQueryData(subscriptionKeys.user(true), updateSubscriptionData)
|
||||||
|
|
||||||
queryClient.setQueryData(subscriptionKeys.usage(), (old: any) => {
|
queryClient.setQueryData(subscriptionKeys.usage(), (old: any) => {
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
@@ -133,19 +136,24 @@ export function useUpdateUsageLimit() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return { previousSubscriptionData, previousUsageData }
|
return { previousSubscriptionData, previousSubscriptionDataWithOrg, previousUsageData }
|
||||||
},
|
},
|
||||||
onError: (_err, _variables, context) => {
|
onError: (_err, _variables, context) => {
|
||||||
if (context?.previousSubscriptionData) {
|
if (context?.previousSubscriptionData) {
|
||||||
queryClient.setQueryData(subscriptionKeys.user(), context.previousSubscriptionData)
|
queryClient.setQueryData(subscriptionKeys.user(false), context.previousSubscriptionData)
|
||||||
|
}
|
||||||
|
if (context?.previousSubscriptionDataWithOrg) {
|
||||||
|
queryClient.setQueryData(
|
||||||
|
subscriptionKeys.user(true),
|
||||||
|
context.previousSubscriptionDataWithOrg
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (context?.previousUsageData) {
|
if (context?.previousUsageData) {
|
||||||
queryClient.setQueryData(subscriptionKeys.usage(), context.previousUsageData)
|
queryClient.setQueryData(subscriptionKeys.usage(), context.previousUsageData)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
|
queryClient.invalidateQueries({ queryKey: subscriptionKeys.all })
|
||||||
queryClient.invalidateQueries({ queryKey: subscriptionKeys.usage() })
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2661,7 +2661,7 @@ export const useCopilotStore = create<CopilotStore>()(
|
|||||||
// Invalidate subscription queries to update usage
|
// Invalidate subscription queries to update usage
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const queryClient = getQueryClient()
|
const queryClient = getQueryClient()
|
||||||
queryClient.invalidateQueries({ queryKey: subscriptionKeys.user() })
|
queryClient.invalidateQueries({ queryKey: subscriptionKeys.all })
|
||||||
}, 1000)
|
}, 1000)
|
||||||
} finally {
|
} finally {
|
||||||
clearTimeout(timeoutId)
|
clearTimeout(timeoutId)
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
# ========================================
|
# ========================================
|
||||||
# Base Stage: Debian-based Bun
|
# Base Stage: Debian-based Bun with Node.js 22
|
||||||
# ========================================
|
# ========================================
|
||||||
FROM oven/bun:1.3.3-slim AS base
|
FROM oven/bun:1.3.3-slim AS base
|
||||||
|
|
||||||
|
# Install Node.js 22 and common dependencies once in base stage
|
||||||
|
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||||
|
apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python3 python3-pip python3-venv make g++ curl ca-certificates bash ffmpeg \
|
||||||
|
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
||||||
|
&& apt-get install -y nodejs
|
||||||
|
|
||||||
# ========================================
|
# ========================================
|
||||||
# Dependencies Stage: Install Dependencies
|
# Dependencies Stage: Install Dependencies
|
||||||
# ========================================
|
# ========================================
|
||||||
FROM base AS deps
|
FROM base AS deps
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install Node.js 22 for isolated-vm compilation (requires node-gyp and V8)
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
python3 make g++ curl ca-certificates \
|
|
||||||
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
|
||||||
&& apt-get install -y nodejs \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
COPY package.json bun.lock turbo.json ./
|
COPY package.json bun.lock turbo.json ./
|
||||||
RUN mkdir -p apps packages/db packages/testing packages/logger
|
RUN mkdir -p apps packages/db packages/testing packages/logger
|
||||||
COPY apps/sim/package.json ./apps/sim/package.json
|
COPY apps/sim/package.json ./apps/sim/package.json
|
||||||
@@ -25,6 +26,7 @@ COPY packages/logger/package.json ./packages/logger/package.json
|
|||||||
|
|
||||||
# Install turbo globally, then dependencies, then rebuild isolated-vm for Node.js
|
# Install turbo globally, then dependencies, then rebuild isolated-vm for Node.js
|
||||||
RUN --mount=type=cache,id=bun-cache,target=/root/.bun/install/cache \
|
RUN --mount=type=cache,id=bun-cache,target=/root/.bun/install/cache \
|
||||||
|
--mount=type=cache,id=npm-cache,target=/root/.npm \
|
||||||
bun install -g turbo && \
|
bun install -g turbo && \
|
||||||
HUSKY=0 bun install --omit=dev --ignore-scripts && \
|
HUSKY=0 bun install --omit=dev --ignore-scripts && \
|
||||||
cd $(readlink -f node_modules/isolated-vm) && npx node-gyp rebuild --release && cd /app
|
cd $(readlink -f node_modules/isolated-vm) && npx node-gyp rebuild --release && cd /app
|
||||||
@@ -89,13 +91,7 @@ RUN bun run build
|
|||||||
FROM base AS runner
|
FROM base AS runner
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Install Node.js 22 (for isolated-vm worker), Python, and other runtime dependencies
|
# Node.js 22, Python, ffmpeg, etc. are already installed in base stage
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
python3 python3-pip python3-venv bash ffmpeg curl ca-certificates \
|
|
||||||
&& curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
|
|
||||||
&& apt-get install -y nodejs \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
# Create non-root user and group
|
# Create non-root user and group
|
||||||
@@ -113,15 +109,15 @@ COPY --from=deps --chown=nextjs:nodejs /app/node_modules/isolated-vm ./node_modu
|
|||||||
# Copy the isolated-vm worker script
|
# Copy the isolated-vm worker script
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/execution/isolated-vm-worker.cjs ./apps/sim/lib/execution/isolated-vm-worker.cjs
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/execution/isolated-vm-worker.cjs ./apps/sim/lib/execution/isolated-vm-worker.cjs
|
||||||
|
|
||||||
# Guardrails setup (files need to be owned by nextjs for runtime)
|
# Guardrails setup with pip caching
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/guardrails/setup.sh ./apps/sim/lib/guardrails/setup.sh
|
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/guardrails/requirements.txt ./apps/sim/lib/guardrails/requirements.txt
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/guardrails/requirements.txt ./apps/sim/lib/guardrails/requirements.txt
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/guardrails/validate_pii.py ./apps/sim/lib/guardrails/validate_pii.py
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/guardrails/validate_pii.py ./apps/sim/lib/guardrails/validate_pii.py
|
||||||
|
|
||||||
# Run guardrails setup as root, then fix ownership of generated venv files
|
# Install Python dependencies with pip cache mount for faster rebuilds
|
||||||
RUN chmod +x ./apps/sim/lib/guardrails/setup.sh && \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
cd ./apps/sim/lib/guardrails && \
|
python3 -m venv ./apps/sim/lib/guardrails/venv && \
|
||||||
./setup.sh && \
|
./apps/sim/lib/guardrails/venv/bin/pip install --upgrade pip && \
|
||||||
|
./apps/sim/lib/guardrails/venv/bin/pip install -r ./apps/sim/lib/guardrails/requirements.txt && \
|
||||||
chown -R nextjs:nodejs /app/apps/sim/lib/guardrails
|
chown -R nextjs:nodejs /app/apps/sim/lib/guardrails
|
||||||
|
|
||||||
# Create .next/cache directory with correct ownership
|
# Create .next/cache directory with correct ownership
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
|
|||||||
# Copy db package (needed by socket)
|
# Copy db package (needed by socket)
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/packages/db ./packages/db
|
COPY --from=builder --chown=nextjs:nodejs /app/packages/db ./packages/db
|
||||||
|
|
||||||
|
# Copy logger package (workspace dependency used by socket)
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/packages/logger ./packages/logger
|
||||||
|
|
||||||
# Copy sim app (changes most frequently - placed last)
|
# Copy sim app (changes most frequently - placed last)
|
||||||
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim ./apps/sim
|
COPY --from=builder --chown=nextjs:nodejs /app/apps/sim ./apps/sim
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user