Compare commits

...

5 Commits

Author SHA1 Message Date
Siddharth Ganesan
fce1423d05 v0.3.46: fix copilot stats updates
v0.3.46: fix copilot stats updates
2025-09-03 13:26:00 -07:00
Siddharth Ganesan
3656d3d7ad Updates (#1237) 2025-09-03 13:19:34 -07:00
Waleed
581929bc01 v0.3.45: fixes for organization invites, custom tool execution 2025-09-03 08:31:56 -07:00
Waleed
11d8188415 fix(rce): always use VM over RCE for custom tools (#1233) 2025-09-03 08:16:50 -07:00
Waleed
36c98d18e9 fix(team): fix organization invitation URL for teams (#1232) 2025-09-03 08:05:38 -07:00
7 changed files with 15 additions and 127 deletions

View File

@@ -12,23 +12,11 @@ import { SIM_AGENT_API_URL_DEFAULT } from '@/lib/sim-agent'
const SIM_AGENT_API_URL = env.SIM_AGENT_API_URL || SIM_AGENT_API_URL_DEFAULT
const BodySchema = z
.object({
// Do NOT send id; messageId is the unique correlator
userId: z.string().optional(),
chatId: z.string().uuid().optional(),
messageId: z.string().optional(),
depth: z.number().int().nullable().optional(),
maxEnabled: z.boolean().nullable().optional(),
createdAt: z.union([z.string().datetime(), z.date()]).optional(),
diffCreated: z.boolean().nullable().optional(),
diffAccepted: z.boolean().nullable().optional(),
duration: z.number().int().nullable().optional(),
inputTokens: z.number().int().nullable().optional(),
outputTokens: z.number().int().nullable().optional(),
aborted: z.boolean().nullable().optional(),
})
.passthrough()
const BodySchema = z.object({
messageId: z.string(),
diffCreated: z.boolean(),
diffAccepted: z.boolean(),
})
export async function POST(req: NextRequest) {
const tracker = createRequestTracker()
@@ -43,15 +31,15 @@ export async function POST(req: NextRequest) {
if (!parsed.success) {
return createBadRequestResponse('Invalid request body for copilot stats')
}
const body = parsed.data as any
// Build outgoing payload for Sim Agent; do not include id
const { messageId, diffCreated, diffAccepted } = parsed.data as any
// Build outgoing payload for Sim Agent with only required fields
const payload: Record<string, any> = {
...body,
userId: body.userId || userId,
createdAt: body.createdAt || new Date().toISOString(),
messageId,
diffCreated,
diffAccepted,
}
payload.id = undefined
const agentRes = await fetch(`${SIM_AGENT_API_URL}/api/stats`, {
method: 'POST',

View File

@@ -585,6 +585,7 @@ export async function POST(req: NextRequest) {
const useE2B =
e2bEnabled &&
!useLocalVM &&
!isCustomTool &&
(lang === CodeLanguage.JavaScript || lang === CodeLanguage.Python)
if (useE2B) {

View File

@@ -339,7 +339,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
organizationEntry[0]?.name || 'organization',
role,
workspaceInvitationsWithNames,
`${env.NEXT_PUBLIC_APP_URL}/invite/organization?id=${orgInvitation.id}`
`${env.NEXT_PUBLIC_APP_URL}/invite/${orgInvitation.id}`
)
emailResult = await sendEmail({
@@ -352,7 +352,7 @@ export async function POST(request: NextRequest, { params }: { params: Promise<{
const emailHtml = await renderInvitationEmail(
inviter[0]?.name || 'Someone',
organizationEntry[0]?.name || 'organization',
`${env.NEXT_PUBLIC_APP_URL}/invite/organization?id=${orgInvitation.id}`,
`${env.NEXT_PUBLIC_APP_URL}/invite/${orgInvitation.id}`,
email
)

View File

@@ -95,25 +95,6 @@ export class BuildWorkflowClientTool extends BaseClientTool {
// Populate diff preview immediately (without marking complete yet)
try {
const diffStore = useWorkflowDiffStore.getState()
// Send early stats upsert with the triggering user message id if available
try {
const { useCopilotStore } = await import('@/stores/copilot/store')
const { currentChat, currentUserMessageId, agentDepth, agentPrefetch } =
useCopilotStore.getState() as any
if (currentChat?.id && currentUserMessageId) {
fetch('/api/copilot/stats', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chatId: currentChat.id,
messageId: currentUserMessageId,
depth: agentDepth,
maxEnabled: agentDepth >= 2 && !agentPrefetch,
diffCreated: true,
}),
}).catch(() => {})
}
} catch {}
await diffStore.setProposedChanges(result.yamlContent)
logger.info('diff proposed changes set')
} catch (e) {

View File

@@ -151,25 +151,6 @@ export class EditWorkflowClientTool extends BaseClientTool {
try {
if (!this.hasAppliedDiff) {
const diffStore = useWorkflowDiffStore.getState()
// Send early stats upsert with the triggering user message id if available
try {
const { useCopilotStore } = await import('@/stores/copilot/store')
const { currentChat, currentUserMessageId, agentDepth, agentPrefetch } =
useCopilotStore.getState() as any
if (currentChat?.id && currentUserMessageId) {
fetch('/api/copilot/stats', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chatId: currentChat.id,
messageId: currentUserMessageId,
depth: agentDepth,
maxEnabled: agentDepth >= 2 && !agentPrefetch,
diffCreated: true,
}),
}).catch(() => {})
}
} catch {}
await diffStore.setProposedChanges(result.yamlContent)
logger.info('diff proposed changes set for edit_workflow')
this.hasAppliedDiff = true

View File

@@ -1685,27 +1685,6 @@ export const useCopilotStore = create<CopilotStore>()(
}).catch(() => {})
} catch {}
}
// Optimistic stats: mark aborted for the in-flight user message
try {
const { currentChat: cc, currentUserMessageId, messageMetaById } = get() as any
if (cc?.id && currentUserMessageId) {
const meta = messageMetaById?.[currentUserMessageId] || null
const agentDepth = meta?.depth
const maxEnabled = meta?.maxEnabled
fetch('/api/copilot/stats', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chatId: cc.id,
messageId: currentUserMessageId,
...(typeof agentDepth === 'number' ? { depth: agentDepth } : {}),
...(typeof maxEnabled === 'boolean' ? { maxEnabled } : {}),
aborted: true,
}),
}).catch(() => {})
}
} catch {}
} catch {
set({ isSendingMessage: false, isAborting: false, abortController: null })
}
@@ -2113,47 +2092,7 @@ export const useCopilotStore = create<CopilotStore>()(
// Post copilot_stats record (input/output tokens can be null for now)
try {
const { messageMetaById } = get() as any
const meta =
(messageMetaById && (messageMetaById as any)[triggerUserMessageId || '']) || null
const agentDepth = meta?.depth ?? get().agentDepth
const maxEnabled = meta?.maxEnabled ?? (agentDepth >= 2 && !get().agentPrefetch)
const { useWorkflowDiffStore } = await import('@/stores/workflow-diff/store')
const diffState = useWorkflowDiffStore.getState() as any
const diffCreated = !!diffState?.isShowingDiff
const diffAccepted = false // acceptance may arrive earlier or later via diff store
const endMs = Date.now()
const duration = Math.max(0, endMs - startTimeMs)
const chatIdToUse = get().currentChat?.id || context.newChatId
// Prefer provided trigger user message id; fallback to last user message
let userMessageIdToUse = triggerUserMessageId
if (!userMessageIdToUse) {
const msgs = get().messages
for (let i = msgs.length - 1; i >= 0; i--) {
const m = msgs[i]
if (m.role === 'user') {
userMessageIdToUse = m.id
break
}
}
}
if (chatIdToUse) {
fetch('/api/copilot/stats', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chatId: chatIdToUse,
messageId: userMessageIdToUse || assistantMessageId,
depth: agentDepth,
maxEnabled,
diffCreated,
diffAccepted,
duration: duration ?? null,
inputTokens: null,
outputTokens: null,
}),
}).catch(() => {})
}
// Removed: stats sending now occurs only on accept/reject with minimal payload
} catch {}
} finally {
clearTimeout(timeoutId)

View File

@@ -303,7 +303,6 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chatId: currentChat.id,
messageId: triggerMessageId,
diffCreated: true,
diffAccepted: true,
@@ -441,7 +440,6 @@ export const useWorkflowDiffStore = create<WorkflowDiffState & WorkflowDiffActio
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chatId: currentChat.id,
messageId: triggerMessageId,
diffCreated: true,
diffAccepted: false,