Skip to content

Commit e1f2bf8

Browse files
authored
improvement(linter): mship linter (#6359)
* improvement(linter): mship linter * Fix
1 parent 5c0c364 commit e1f2bf8

3 files changed

Lines changed: 92 additions & 1 deletion

File tree

apps/desktop/src/main/channel-identity.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { describe, expect, it } from 'vitest'
1+
import { describe, expect, it, vi } from 'vitest'
2+
3+
vi.mock('electron', () => import('@/test/electron-mock'))
4+
25
import { APP_NAME_FOR_CHANNEL, channelForOrigin, DEFAULT_ORIGIN } from '@/main/config'
36
import { classifyNavigation } from '@/main/navigation'
47
import { DEV, identityForOrigin, LOCAL, PROD, STAGING } from '../../scripts/channels'

apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,29 @@ const oauthBlockConfig = {
3838
tools: { access: ['slack_message'] },
3939
}
4040

41+
const tableBlockConfig = {
42+
type: 'table',
43+
name: 'Table',
44+
outputs: {},
45+
subBlocks: [
46+
{
47+
id: 'operation',
48+
type: 'dropdown',
49+
options: [
50+
{ label: 'Query Rows', id: 'query_rows' },
51+
{ label: 'Insert Row', id: 'insert_row' },
52+
],
53+
},
54+
],
55+
tools: {
56+
access: ['table_query_rows', 'table_insert_row'],
57+
config: {
58+
tool: (params: Record<string, unknown>) =>
59+
params.operation === 'insert_row' ? 'table_insert_row' : 'table_query_rows',
60+
},
61+
},
62+
}
63+
4164
const routerBlockConfig = {
4265
type: 'router_v2',
4366
name: 'Router',
@@ -205,6 +228,7 @@ const toolsByIdMock: Record<string, unknown> = {
205228
const blockConfigsByType: Record<string, unknown> = {
206229
condition: conditionBlockConfig,
207230
slack: oauthBlockConfig,
231+
table: tableBlockConfig,
208232
router_v2: routerBlockConfig,
209233
agent: agentBlockConfig,
210234
pi: piBlockConfig,
@@ -1239,6 +1263,42 @@ describe('validateInputsForBlock - agent tools (tool-input)', () => {
12391263
expect(result.validInputs.tools).toBeDefined()
12401264
})
12411265

1266+
it('accepts a declared integration block operation', () => {
1267+
const result = validateInputsForBlock(
1268+
'agent',
1269+
{ tools: [{ type: 'table', operation: 'insert_row', usageControl: 'auto' }] },
1270+
'agent-1'
1271+
)
1272+
1273+
expect(result.errors).toHaveLength(0)
1274+
expect(result.validInputs.tools).toBeDefined()
1275+
})
1276+
1277+
it('rejects a prefixed tool id used as an integration block operation', () => {
1278+
const result = validateInputsForBlock(
1279+
'agent',
1280+
{ tools: [{ type: 'table', operation: 'table_insert_row', usageControl: 'auto' }] },
1281+
'agent-1'
1282+
)
1283+
1284+
expect(result.validInputs.tools).toBeUndefined()
1285+
expect(result.errors).toHaveLength(1)
1286+
expect(result.errors[0]?.error).toContain('invalid operation "table_insert_row"')
1287+
expect(result.errors[0]?.error).toContain('query_rows, insert_row')
1288+
expect(result.errors[0]?.error).toContain('may differ from the underlying tool id')
1289+
})
1290+
1291+
it('rejects a missing operation for a multi-operation integration block', () => {
1292+
const result = validateInputsForBlock(
1293+
'agent',
1294+
{ tools: [{ type: 'table', usageControl: 'auto' }] },
1295+
'agent-1'
1296+
)
1297+
1298+
expect(result.validInputs.tools).toBeUndefined()
1299+
expect(result.errors[0]?.error).toContain('requires an operation')
1300+
})
1301+
12421302
it('rejects an integration tool unavailable in this deployment', () => {
12431303
mockIsIntegrationDeploymentAvailable.mockReturnValue(false)
12441304

apps/sim/lib/copilot/tools/server/workflow/edit-workflow/validation.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,34 @@ function validateAgentToolEntry(item: any, index: number): string | null {
248248
if (!isIntegrationDeploymentAvailableForVisibility(type, overlayVisibility())) {
249249
return `${where} block type "${type}" is unavailable in this deployment`
250250
}
251+
252+
const operationConfig = block.subBlocks?.find((subBlock) => subBlock.id === 'operation')
253+
if (operationConfig?.options) {
254+
let validOperations: string[]
255+
try {
256+
const options =
257+
typeof operationConfig.options === 'function'
258+
? operationConfig.options()
259+
: operationConfig.options
260+
validOperations = options.map((option) => option.id)
261+
} catch (error) {
262+
return `${where} could not validate operations for block type "${type}": ${toError(error).message}`
263+
}
264+
265+
const operation = item.operation
266+
if (
267+
validOperations.length > 1 &&
268+
(typeof operation !== 'string' || operation.trim() === '')
269+
) {
270+
return `${where} block type "${type}" requires an operation. Valid operations: ${validOperations.join(', ')}`
271+
}
272+
if (
273+
operation !== undefined &&
274+
(typeof operation !== 'string' || !validOperations.includes(operation))
275+
) {
276+
return `${where} block type "${type}" has invalid operation "${String(operation)}". Valid operations: ${validOperations.join(', ')}. Use one of the block operation ids above; it may differ from the underlying tool id.`
277+
}
278+
}
251279
}
252280

253281
return null

0 commit comments

Comments
 (0)