@membranehq/cli 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/index.js +140 -140
  2. package/package.json +16 -4
  3. package/.turbo/turbo-build.log +0 -9
  4. package/CHANGELOG.md +0 -7
  5. package/scripts/add-shebang.sh +0 -6
  6. package/scripts/prepare-package-json.ts +0 -29
  7. package/src/agent.tsx +0 -50
  8. package/src/cli.ts +0 -72
  9. package/src/commands/open.command.ts +0 -51
  10. package/src/commands/pull.command.ts +0 -75
  11. package/src/commands/push.command.ts +0 -79
  12. package/src/commands/test.command.ts +0 -99
  13. package/src/components/AddMcpServerScreen.tsx +0 -215
  14. package/src/components/AgentStatus.tsx +0 -15
  15. package/src/components/Main.tsx +0 -64
  16. package/src/components/OverviewSection.tsx +0 -24
  17. package/src/components/PersonalAccessTokenInput.tsx +0 -56
  18. package/src/components/RecentChanges.tsx +0 -65
  19. package/src/components/SelectWorkspace.tsx +0 -112
  20. package/src/components/Setup.tsx +0 -121
  21. package/src/components/WorkspaceStatus.tsx +0 -61
  22. package/src/contexts/FileWatcherContext.tsx +0 -81
  23. package/src/index.ts +0 -27
  24. package/src/legacy/commands/pullWorkspace.ts +0 -70
  25. package/src/legacy/commands/pushWorkspace.ts +0 -246
  26. package/src/legacy/integrationElements.ts +0 -78
  27. package/src/legacy/push/types.ts +0 -17
  28. package/src/legacy/reader/index.ts +0 -113
  29. package/src/legacy/types.ts +0 -17
  30. package/src/legacy/util.ts +0 -149
  31. package/src/legacy/workspace-elements/connectors.ts +0 -397
  32. package/src/legacy/workspace-elements/index.ts +0 -27
  33. package/src/legacy/workspace-tools/commands/pullWorkspace.ts +0 -70
  34. package/src/legacy/workspace-tools/integrationElements.ts +0 -78
  35. package/src/legacy/workspace-tools/util.ts +0 -149
  36. package/src/mcp/server-status.ts +0 -27
  37. package/src/mcp/server.ts +0 -36
  38. package/src/mcp/tools/getTestAccessToken.ts +0 -32
  39. package/src/modules/api/account-api-client.ts +0 -89
  40. package/src/modules/api/index.ts +0 -3
  41. package/src/modules/api/membrane-api-client.ts +0 -116
  42. package/src/modules/api/workspace-api-client.ts +0 -11
  43. package/src/modules/config/cwd-context.tsx +0 -11
  44. package/src/modules/config/project/getAgentVersion.ts +0 -16
  45. package/src/modules/config/project/index.ts +0 -8
  46. package/src/modules/config/project/paths.ts +0 -25
  47. package/src/modules/config/project/readProjectConfig.ts +0 -27
  48. package/src/modules/config/project/useProjectConfig.tsx +0 -103
  49. package/src/modules/config/system/index.ts +0 -35
  50. package/src/modules/file-watcher/index.ts +0 -166
  51. package/src/modules/file-watcher/types.ts +0 -14
  52. package/src/modules/setup/steps.ts +0 -9
  53. package/src/modules/setup/useSetup.ts +0 -16
  54. package/src/modules/status/useStatus.ts +0 -16
  55. package/src/modules/workspace-element-service/constants.ts +0 -121
  56. package/src/modules/workspace-element-service/getTypeAndKeyFromPath.ts +0 -69
  57. package/src/modules/workspace-element-service/index.ts +0 -304
  58. package/src/testing/environment.ts +0 -172
  59. package/src/testing/runners/base.runner.ts +0 -27
  60. package/src/testing/runners/test.runner.ts +0 -123
  61. package/src/testing/scripts/generate-test-report.ts +0 -757
  62. package/src/testing/test-suites/base.ts +0 -92
  63. package/src/testing/test-suites/data-collection.ts +0 -128
  64. package/src/testing/testers/base.ts +0 -115
  65. package/src/testing/testers/create.ts +0 -273
  66. package/src/testing/testers/delete.ts +0 -155
  67. package/src/testing/testers/find-by-id.ts +0 -135
  68. package/src/testing/testers/list.ts +0 -110
  69. package/src/testing/testers/match.ts +0 -149
  70. package/src/testing/testers/search.ts +0 -148
  71. package/src/testing/testers/spec.ts +0 -30
  72. package/src/testing/testers/update.ts +0 -284
  73. package/src/utils/auth.ts +0 -19
  74. package/src/utils/constants.ts +0 -27
  75. package/src/utils/fields.ts +0 -83
  76. package/src/utils/logger.ts +0 -106
  77. package/src/utils/templating.ts +0 -50
  78. package/tsconfig.json +0 -21
@@ -1,155 +0,0 @@
1
- import { DataCollectionSpec, extractIntegrationAppErrorData } from '@integration-app/sdk'
2
- import chalk from 'chalk'
3
-
4
- import { TestEnvironment } from '../environment'
5
- import { BaseTester } from './base'
6
-
7
- interface DataCollectionDeleteTestConfig {
8
- input: {
9
- id: string
10
- }
11
- }
12
-
13
- export class DataCollectionDeleteTester extends BaseTester<DataCollectionDeleteTestConfig> {
14
- private dataCollectionKey: string
15
- private dataCollection: DataCollectionSpec
16
-
17
- constructor({
18
- environment,
19
- dataCollectionKey,
20
- dataCollection,
21
- }: {
22
- environment: TestEnvironment
23
- dataCollectionKey: string
24
- dataCollection: DataCollectionSpec
25
- }) {
26
- super({
27
- environment,
28
- path: `data/${dataCollectionKey}/delete`,
29
- })
30
-
31
- this.dataCollectionKey = dataCollectionKey
32
- this.dataCollection = dataCollection
33
- }
34
-
35
- async run(config?: DataCollectionDeleteTestConfig): Promise<void> {
36
- const id =
37
- (
38
- this.environment.state[this.dataCollectionKey] as {
39
- createdRecordId: string
40
- }
41
- )?.createdRecordId || config?.input?.id
42
- if (!id) {
43
- throw new Error(`No ID found in state or config for ${this.dataCollectionKey} delete`)
44
- }
45
-
46
- try {
47
- await this.environment.client
48
- .connection(this.environment.connectionId)
49
- .dataCollection(this.dataCollectionKey)
50
- .delete({ id })
51
- } catch (deleteError: any) {
52
- throw deleteError
53
- }
54
-
55
- if (this.dataCollection.findById) {
56
- try {
57
- await this.environment.client
58
- .connection(this.environment.connectionId)
59
- .dataCollection(this.dataCollectionKey)
60
- .findById({
61
- id,
62
- })
63
- } catch (error: any) {
64
- if (error?.data?.data?.response?.status === 404) {
65
- await this.assert(() => true, 'Record is not found after deletion')
66
- return
67
- }
68
-
69
- throw error
70
- }
71
- } else {
72
- await this.assert(() => true, 'No findById capability, skipping verification')
73
- }
74
- }
75
-
76
- async generateConfig(): Promise<DataCollectionDeleteTestConfig> {
77
- let id = (
78
- this.environment.state[this.dataCollectionKey] as {
79
- createdRecordId: string
80
- }
81
- )?.createdRecordId
82
-
83
- if (!id) {
84
- if (!this.dataCollection.list) {
85
- throw new Error(
86
- `Can't find a record to test delete operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`,
87
- )
88
- }
89
-
90
- const listResponse = await this.environment.client
91
- .connection(this.environment.connectionId)
92
- .dataCollection(this.dataCollectionKey)
93
- .list({})
94
-
95
- if (!listResponse?.records?.length) {
96
- throw new Error(`No records found to test delete for ${this.dataCollectionKey}`)
97
- }
98
-
99
- id = listResponse.records[0].id
100
- }
101
-
102
- return {
103
- input: {
104
- id,
105
- },
106
- }
107
- }
108
-
109
- protected async fixTestCase({
110
- config,
111
- error,
112
- }: {
113
- config: DataCollectionDeleteTestConfig
114
- error: any
115
- }): Promise<DataCollectionDeleteTestConfig> {
116
- const errorData = extractIntegrationAppErrorData(error)
117
-
118
- const prompt = `I'm trying to delete a record from a data collection.
119
-
120
- I tried to delete a record with this ID:
121
-
122
- ${JSON.stringify(config.input?.id, null, 2)}
123
-
124
- But got this error:
125
-
126
- ${JSON.stringify(errorData)}
127
-
128
- Please analyze the error and provide:
129
- 1. A fixed ID that would work (as a string)
130
- 2. A short explanation of what was wrong with the original ID
131
-
132
- Format your response as a JSON object with two fields:
133
- {
134
- "explanation": "short explanation of what was wrong and how you fixed it",
135
- "id": "fixed id"
136
- }.
137
-
138
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`
139
-
140
- const response = await this.environment.llm.complete({
141
- prompt,
142
- maxTokens: 1000,
143
- })
144
-
145
- const result = JSON.parse(response.trim())
146
-
147
- console.warn(chalk.bold.yellow('[auto-fix]'), `${this.path}:`, result.explanation)
148
-
149
- return {
150
- input: {
151
- id: result.id,
152
- },
153
- }
154
- }
155
- }
@@ -1,135 +0,0 @@
1
- import { DataCollectionSpec, extractIntegrationAppErrorData } from '@integration-app/sdk'
2
- import chalk from 'chalk'
3
-
4
- import { TestEnvironment } from '../environment'
5
- import { BaseTester } from './base'
6
-
7
- interface DataCollectionFindByIdTestConfig {
8
- input: {
9
- id: string
10
- }
11
- }
12
-
13
- export class DataCollectionFindByIdTester extends BaseTester<DataCollectionFindByIdTestConfig> {
14
- private dataCollectionKey: string
15
- private dataCollection: DataCollectionSpec
16
-
17
- constructor({
18
- environment,
19
- dataCollectionKey,
20
- dataCollection,
21
- }: {
22
- environment: TestEnvironment
23
- dataCollectionKey: string
24
- dataCollection: DataCollectionSpec
25
- }) {
26
- super({
27
- environment,
28
- path: `data/${dataCollectionKey}/find-by-id`,
29
- })
30
-
31
- this.dataCollectionKey = dataCollectionKey
32
- this.dataCollection = dataCollection
33
- }
34
-
35
- async run(config?: DataCollectionFindByIdTestConfig): Promise<void> {
36
- const id =
37
- (
38
- this.environment.state[this.dataCollectionKey] as {
39
- createdRecordId: string
40
- }
41
- )?.createdRecordId || config?.input?.id
42
- if (!id) {
43
- throw new Error(`No ID found in state or config for ${this.dataCollectionKey} find-by-id`)
44
- }
45
-
46
- const findByIdResponse = await this.environment.client
47
- .connection(this.environment.connectionId)
48
- .dataCollection(this.dataCollectionKey)
49
- .findById({ id })
50
-
51
- await this.assert(() => !!findByIdResponse.record, 'Record is returned from findById')
52
-
53
- await this.assert(() => findByIdResponse.record.id === id, 'Returned record ID matches requested ID')
54
- }
55
-
56
- async generateConfig(): Promise<DataCollectionFindByIdTestConfig> {
57
- let id = (
58
- this.environment.state[this.dataCollectionKey] as {
59
- createdRecordId: string
60
- }
61
- )?.createdRecordId
62
-
63
- if (!id) {
64
- if (!this.dataCollection.list) {
65
- throw new Error(
66
- `Can't find a record to test findById operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`,
67
- )
68
- }
69
-
70
- const listResponse = await this.environment.client
71
- .connection(this.environment.connectionId)
72
- .dataCollection(this.dataCollectionKey)
73
- .list({})
74
-
75
- if (!listResponse?.records?.length) {
76
- throw new Error(`No records found to test findById for ${this.dataCollectionKey}`)
77
- }
78
-
79
- id = listResponse.records[0].id
80
- }
81
-
82
- return {
83
- input: {
84
- id,
85
- },
86
- }
87
- }
88
-
89
- protected async fixTestCase({
90
- config,
91
- error,
92
- }: {
93
- config: DataCollectionFindByIdTestConfig
94
- error: any
95
- }): Promise<DataCollectionFindByIdTestConfig> {
96
- const errorData = extractIntegrationAppErrorData(error)
97
-
98
- const prompt = `I'm trying to find a record by ID in a data collection.
99
-
100
- I tried to find a record with this ID:
101
-
102
- ${JSON.stringify(config.input?.id, null, 2)}
103
-
104
- But got this error:
105
-
106
- ${JSON.stringify(errorData)}
107
-
108
- Please analyze the error and provide:
109
- 1. A fixed ID that would work (as a string)
110
- 2. A short explanation of what was wrong with the original ID
111
-
112
- Format your response as a JSON object with two fields:
113
- {
114
- "explanation": "short explanation of what was wrong and how you fixed it",
115
- "id": "fixed id"
116
- }.
117
-
118
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`
119
-
120
- const response = await this.environment.llm.complete({
121
- prompt,
122
- maxTokens: 1000,
123
- })
124
-
125
- const result = JSON.parse(response.trim())
126
-
127
- console.warn(chalk.bold.yellow('[auto-fix]'), `${this.path}:`, result.explanation)
128
-
129
- return {
130
- input: {
131
- id: result.id,
132
- },
133
- }
134
- }
135
- }
@@ -1,110 +0,0 @@
1
- import { extractIntegrationAppErrorData } from '@integration-app/sdk'
2
- import chalk from 'chalk'
3
-
4
- import { TestEnvironment } from '../environment'
5
- import { BaseTester } from './base'
6
-
7
- interface DataCollectionListTestConfig {
8
- input: {
9
- sort?: {
10
- field: string
11
- direction: 'asc' | 'desc'
12
- }
13
- filter?: Record<string, any>
14
- }
15
- }
16
-
17
- export class DataCollectionListTester extends BaseTester<DataCollectionListTestConfig> {
18
- private dataCollectionKey: string
19
-
20
- constructor({ environment, dataCollectionKey }: { environment: TestEnvironment; dataCollectionKey: string }) {
21
- super({
22
- environment,
23
- path: `data/${dataCollectionKey}/list`,
24
- })
25
-
26
- this.dataCollectionKey = dataCollectionKey
27
- }
28
-
29
- async run(config: DataCollectionListTestConfig): Promise<void> {
30
- const listResponse = await this.environment.client
31
- .connection(this.environment.connectionId)
32
- .dataCollection(this.dataCollectionKey)
33
- .list(config.input)
34
-
35
- await this.assert(() => Array.isArray(listResponse.records), 'Response has records field as array')
36
-
37
- if (config.input.sort) {
38
- const { field, direction } = config.input.sort
39
- const records = listResponse.records
40
-
41
- if (records.length > 1) {
42
- for (let i = 1; i < records.length; i++) {
43
- const prev = records[i - 1].fields[field]
44
- const curr = records[i].fields[field]
45
-
46
- // Skip comparison if either value is null/undefined
47
- if (prev == null || curr == null) continue
48
-
49
- // Use proper comparison logic
50
- if (direction === 'asc') {
51
- await this.assert(() => prev <= curr, `Records are sorted by ${field} in ascending order`)
52
- } else {
53
- await this.assert(() => prev >= curr, `Records are sorted by ${field} in descending order`)
54
- }
55
- }
56
- }
57
- }
58
- }
59
-
60
- async generateConfig(): Promise<DataCollectionListTestConfig> {
61
- return {
62
- input: {},
63
- }
64
- }
65
-
66
- protected async fixTestCase({
67
- config,
68
- error,
69
- }: {
70
- config: DataCollectionListTestConfig
71
- error: any
72
- }): Promise<DataCollectionListTestConfig> {
73
- const errorData = extractIntegrationAppErrorData(error)
74
-
75
- const prompt = `I'm trying to list records from a data collection.
76
-
77
- I tried to list records with these parameters:
78
-
79
- ${JSON.stringify(config.input, null, 2)}
80
-
81
- But got this error:
82
-
83
- ${JSON.stringify(errorData)}
84
-
85
- Please analyze the error and provide:
86
- 1. Fixed parameters that would work (as a JSON object)
87
- 2. A short explanation of what was wrong with the original parameters
88
-
89
- Format your response as a JSON object with two fields:
90
- {
91
- "explanation": "short explanation of what was wrong and how you fixed it",
92
- "input": { ... fixed parameters ... }
93
- }.
94
-
95
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`
96
-
97
- const response = await this.environment.llm.complete({
98
- prompt,
99
- maxTokens: 1000,
100
- })
101
-
102
- const result = JSON.parse(response.trim())
103
-
104
- console.warn(chalk.bold.yellow('[auto-fix]'), `${this.path}:`, result.explanation)
105
-
106
- return {
107
- input: result.input,
108
- }
109
- }
110
- }
@@ -1,149 +0,0 @@
1
- import { DataCollectionSpec, extractIntegrationAppErrorData } from '@integration-app/sdk'
2
- import chalk from 'chalk'
3
-
4
- import { TestEnvironment } from '../environment'
5
- import { BaseTester } from './base'
6
- import { softCompare } from '../../utils/fields'
7
-
8
- interface DataCollectionMatchTestConfig {
9
- input: {
10
- query: Record<string, any>
11
- }
12
- }
13
-
14
- export class DataCollectionMatchTester extends BaseTester<DataCollectionMatchTestConfig> {
15
- private dataCollectionKey: string
16
- private dataCollection: DataCollectionSpec
17
-
18
- constructor({
19
- environment,
20
- dataCollectionKey,
21
- dataCollection,
22
- }: {
23
- environment: TestEnvironment
24
- dataCollectionKey: string
25
- dataCollection: DataCollectionSpec
26
- }) {
27
- super({
28
- environment,
29
- path: `data/${dataCollectionKey}/match`,
30
- })
31
-
32
- this.dataCollectionKey = dataCollectionKey
33
- this.dataCollection = dataCollection
34
- }
35
-
36
- async run(config: DataCollectionMatchTestConfig): Promise<void> {
37
- const matchResponse = await this.environment.client
38
- .connection(this.environment.connectionId)
39
- .dataCollection(this.dataCollectionKey)
40
- .match(config.input)
41
-
42
- await this.assert(() => !!matchResponse.record, 'Response contains a record')
43
-
44
- const matchedRecord = matchResponse.record
45
- const fullRecordResponse = await this.environment.client
46
- .connection(this.environment.connectionId)
47
- .dataCollection(this.dataCollectionKey)
48
- .findById({ id: matchedRecord.id })
49
-
50
- const record = fullRecordResponse.record
51
- for (const [key, value] of Object.entries(config.input.query)) {
52
- const actualValue = record.fields[key]
53
- await this.assert(
54
- () => softCompare(actualValue, value),
55
- `Record field ${key} matches input value - expected ${JSON.stringify(value)} got ${JSON.stringify(actualValue)}`,
56
- )
57
- }
58
- }
59
-
60
- async generateConfig(): Promise<DataCollectionMatchTestConfig> {
61
- if (!this.dataCollection.list) {
62
- throw new Error(
63
- `Can't find a record to test match operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`,
64
- )
65
- }
66
-
67
- const listResponse = await this.environment.client
68
- .connection(this.environment.connectionId)
69
- .dataCollection(this.dataCollectionKey)
70
- .list({})
71
-
72
- if (!listResponse?.records?.length) {
73
- throw new Error('No records found to test match')
74
- }
75
-
76
- const record = listResponse.records[0]
77
- if (!record?.fields) {
78
- throw new Error('First record has no fields to match against')
79
- }
80
-
81
- const query: Record<string, any> = {}
82
- const fields = record.fields || {}
83
-
84
- const fieldEntries = Object.entries(fields)
85
- .filter(([key, value]) => key !== 'links' && value != null && value !== '')
86
- .slice(0, 1)
87
-
88
- if (fieldEntries.length === 0) {
89
- throw new Error('No usable fields found in record for matching')
90
- }
91
-
92
- for (const [key, value] of fieldEntries) {
93
- query[key] = value
94
- }
95
-
96
- return {
97
- input: {
98
- query,
99
- },
100
- }
101
- }
102
-
103
- protected async fixTestCase({
104
- config,
105
- error,
106
- }: {
107
- config: DataCollectionMatchTestConfig
108
- error: any
109
- }): Promise<DataCollectionMatchTestConfig> {
110
- const errorData = extractIntegrationAppErrorData(error)
111
-
112
- const prompt = `I'm trying to match a record in a data collection.
113
-
114
- I tried to match a record with this query:
115
-
116
- ${JSON.stringify(config.input?.query, null, 2)}
117
-
118
- But got this error:
119
-
120
- ${JSON.stringify(errorData)}
121
-
122
- Please analyze the error and provide:
123
- 1. Fixed query that would work (as a JSON object)
124
- 2. A short explanation of what was wrong with the original query
125
-
126
- Format your response as a JSON object with two fields:
127
- {
128
- "explanation": "short explanation of what was wrong and how you fixed it",
129
- "query": { ... fixed query ... }
130
- }.
131
-
132
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`
133
-
134
- const response = await this.environment.llm.complete({
135
- prompt,
136
- maxTokens: 1000,
137
- })
138
-
139
- const result = JSON.parse(response.trim())
140
-
141
- console.warn(chalk.bold.yellow('[auto-fix]'), `${this.path}:`, result.explanation)
142
-
143
- return {
144
- input: {
145
- query: result.query,
146
- },
147
- }
148
- }
149
- }
@@ -1,148 +0,0 @@
1
- import { DataCollectionSpec, extractIntegrationAppErrorData } from '@integration-app/sdk'
2
- import chalk from 'chalk'
3
-
4
- import { TestEnvironment } from '../environment'
5
- import { BaseTester } from './base'
6
-
7
- interface DataCollectionSearchTestConfig {
8
- input: {
9
- query: string
10
- }
11
- expectedRecordId: string
12
- }
13
-
14
- export class DataCollectionSearchTester extends BaseTester<DataCollectionSearchTestConfig> {
15
- private dataCollectionKey: string
16
- private dataCollection: DataCollectionSpec
17
-
18
- constructor({
19
- environment,
20
- dataCollectionKey,
21
- dataCollection,
22
- }: {
23
- environment: TestEnvironment
24
- dataCollectionKey: string
25
- dataCollection: DataCollectionSpec
26
- }) {
27
- super({
28
- environment,
29
- path: `data/${dataCollectionKey}/search`,
30
- })
31
-
32
- this.dataCollectionKey = dataCollectionKey
33
- this.dataCollection = dataCollection
34
- }
35
-
36
- async run(config: DataCollectionSearchTestConfig): Promise<void> {
37
- const searchResponse = await this.environment.client
38
- .connection(this.environment.connectionId)
39
- .dataCollection(this.dataCollectionKey)
40
- .search(config.input)
41
-
42
- await this.assert(() => Array.isArray(searchResponse.records), 'Response has records field as array')
43
-
44
- const foundExpectedRecord = searchResponse.records.some((r) => r.id === config.expectedRecordId)
45
-
46
- if (!foundExpectedRecord) {
47
- console.debug(chalk.yellow(`Search query "${config.input.query}" did not return expected record`))
48
- }
49
-
50
- await this.assert(() => foundExpectedRecord, 'Search returns expected record')
51
- }
52
-
53
- async generateConfig(): Promise<DataCollectionSearchTestConfig> {
54
- if (!this.dataCollection.list) {
55
- throw new Error(
56
- `Can't find a record to test search operation for ${this.dataCollectionKey}. List operation is not implemented for this data collection`,
57
- )
58
- }
59
-
60
- const listResponse = await this.environment.client
61
- .connection(this.environment.connectionId)
62
- .dataCollection(this.dataCollectionKey)
63
- .list({})
64
-
65
- if (!listResponse.records.length) {
66
- throw new Error('No records found to test search')
67
- }
68
-
69
- const record = listResponse.records[0]
70
-
71
- // Ask LLM for candidate query string
72
- const candidateQuery = await this.getSearchQueryWithLLM(record.fields)
73
-
74
- if (!candidateQuery) {
75
- throw new Error(
76
- 'Unable to generate search query. LLM could not identify a suitable field value from the record to use as the search query.',
77
- )
78
- }
79
-
80
- return {
81
- input: { query: candidateQuery },
82
- expectedRecordId: record.id,
83
- }
84
- }
85
-
86
- private async getSearchQueryWithLLM(fields: Record<string, any>): Promise<string | null> {
87
- const prompt = `You are given the fields of a record from a data collection. Identify the BEST single field value that a user is MOST likely to type when searching for this record (e.g. name, title, email, external id). Ignore null, empty strings, technical IDs, HTML, and timestamps unless they are obviously human-searchable. Make sure the field value is as unique as possible for this record. RETURN ONLY the field value as a plain string. No additional text, no JSON, no quotes.
88
-
89
- Record fields:
90
- ${JSON.stringify(fields, null, 2)}
91
-
92
- Field value:`
93
-
94
- try {
95
- const response = await this.environment.llm.complete({ prompt, maxTokens: 1000 })
96
- return response.trim() || null
97
- } catch (_) {
98
- // TODO: it's a good idea to retry or change the prompt
99
- return null
100
- }
101
- }
102
-
103
- protected async fixTestCase({
104
- config,
105
- error,
106
- }: {
107
- config: DataCollectionSearchTestConfig
108
- error: any
109
- }): Promise<DataCollectionSearchTestConfig> {
110
- const errorData = extractIntegrationAppErrorData(error)
111
-
112
- const prompt = `I'm trying to search records in a data collection.
113
-
114
- I tried to search records with these parameters:
115
-
116
- ${JSON.stringify(config.input, null, 2)}
117
-
118
- But got this error:
119
-
120
- ${JSON.stringify(errorData)}
121
-
122
- Please analyze the error and provide:
123
- 1. Fixed parameters that would work (as a JSON object)
124
- 2. A short explanation of what was wrong with the original parameters
125
-
126
- Format your response as a JSON object with two fields:
127
- {
128
- "explanation": "short explanation of what was wrong and how you fixed it",
129
- "input": { ... fixed parameters ... }
130
- }.
131
-
132
- Only return the JSON object, no other text or wrapping (like \`\`\`json or \`\`\`).`
133
-
134
- const response = await this.environment.llm.complete({
135
- prompt,
136
- maxTokens: 1000,
137
- })
138
-
139
- const result = JSON.parse(response.trim())
140
-
141
- console.warn(chalk.bold.yellow('[auto-fix]'), `${this.path}:`, result.explanation)
142
-
143
- return {
144
- input: result.input,
145
- expectedRecordId: config.expectedRecordId,
146
- }
147
- }
148
- }