@observeone/cli 1.1.0 → 1.2.1

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 (82) hide show
  1. package/README.md +37 -61
  2. package/dist/README.md +37 -61
  3. package/dist/commands/ai-check.d.ts.map +1 -1
  4. package/dist/commands/ai-check.js +35 -28
  5. package/dist/commands/ai-check.js.map +1 -1
  6. package/dist/commands/apply.d.ts.map +1 -1
  7. package/dist/commands/apply.js +30 -21
  8. package/dist/commands/apply.js.map +1 -1
  9. package/dist/commands/check.d.ts.map +1 -1
  10. package/dist/commands/check.js +30 -225
  11. package/dist/commands/check.js.map +1 -1
  12. package/dist/commands/export.d.ts.map +1 -1
  13. package/dist/commands/export.js +3 -3
  14. package/dist/commands/export.js.map +1 -1
  15. package/dist/commands/heartbeat.d.ts +1 -1
  16. package/dist/commands/heartbeat.d.ts.map +1 -1
  17. package/dist/commands/heartbeat.js +39 -234
  18. package/dist/commands/heartbeat.js.map +1 -1
  19. package/dist/commands/init.d.ts.map +1 -1
  20. package/dist/commands/init.js +2 -1
  21. package/dist/commands/init.js.map +1 -1
  22. package/dist/commands/login.js +7 -9
  23. package/dist/commands/login.js.map +1 -1
  24. package/dist/commands/monitor.d.ts +1 -1
  25. package/dist/commands/monitor.d.ts.map +1 -1
  26. package/dist/commands/monitor.js +32 -235
  27. package/dist/commands/monitor.js.map +1 -1
  28. package/dist/commands/resource-command.factory.d.ts +31 -0
  29. package/dist/commands/resource-command.factory.d.ts.map +1 -0
  30. package/dist/commands/resource-command.factory.js +208 -0
  31. package/dist/commands/resource-command.factory.js.map +1 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +12 -8
  34. package/dist/index.js.map +1 -1
  35. package/dist/interfaces/api-client.interface.d.ts +6 -9
  36. package/dist/interfaces/api-client.interface.d.ts.map +1 -1
  37. package/dist/interfaces/config.interface.d.ts +5 -10
  38. package/dist/interfaces/config.interface.d.ts.map +1 -1
  39. package/dist/interfaces/output.interface.d.ts +20 -3
  40. package/dist/interfaces/output.interface.d.ts.map +1 -1
  41. package/dist/interfaces/sse-client.interface.d.ts +3 -3
  42. package/dist/interfaces/sse-client.interface.d.ts.map +1 -1
  43. package/dist/package.json +1 -1
  44. package/dist/services/api-client.service.d.ts +4 -7
  45. package/dist/services/api-client.service.d.ts.map +1 -1
  46. package/dist/services/api-client.service.js +32 -33
  47. package/dist/services/api-client.service.js.map +1 -1
  48. package/dist/services/config.service.d.ts +7 -12
  49. package/dist/services/config.service.d.ts.map +1 -1
  50. package/dist/services/config.service.js +47 -18
  51. package/dist/services/config.service.js.map +1 -1
  52. package/dist/services/output.service.d.ts +20 -3
  53. package/dist/services/output.service.d.ts.map +1 -1
  54. package/dist/services/output.service.js +11 -10
  55. package/dist/services/output.service.js.map +1 -1
  56. package/dist/services/sse-client.service.d.ts +1 -1
  57. package/dist/services/sse-client.service.d.ts.map +1 -1
  58. package/dist/services/sse-client.service.js +2 -1
  59. package/dist/services/sse-client.service.js.map +1 -1
  60. package/dist/services/update.service.d.ts +13 -0
  61. package/dist/services/update.service.d.ts.map +1 -0
  62. package/dist/services/update.service.js +57 -0
  63. package/dist/services/update.service.js.map +1 -0
  64. package/dist/types/index.d.ts +37 -35
  65. package/dist/types/index.d.ts.map +1 -1
  66. package/dist/utils/deep-equal.d.ts +2 -2
  67. package/dist/utils/deep-equal.d.ts.map +1 -1
  68. package/dist/utils/deep-equal.js +6 -4
  69. package/dist/utils/deep-equal.js.map +1 -1
  70. package/dist/utils/live-progress.d.ts +10 -1
  71. package/dist/utils/live-progress.d.ts.map +1 -1
  72. package/dist/utils/live-progress.js +5 -5
  73. package/dist/utils/live-progress.js.map +1 -1
  74. package/dist/utils/log-writer.d.ts +15 -2
  75. package/dist/utils/log-writer.d.ts.map +1 -1
  76. package/dist/utils/log-writer.js +1 -1
  77. package/dist/utils/log-writer.js.map +1 -1
  78. package/package.json +1 -1
  79. package/dist/commands/signup.d.ts +0 -9
  80. package/dist/commands/signup.d.ts.map +0 -1
  81. package/dist/commands/signup.js +0 -53
  82. package/dist/commands/signup.js.map +0 -1
package/README.md CHANGED
@@ -19,6 +19,7 @@ npm install -g @observeone/cli
19
19
 
20
20
  2. **Initialize Workspace**
21
21
  ```bash
22
+ # Creates local .obs.config.json
22
23
  obs init
23
24
  ```
24
25
 
@@ -27,7 +28,7 @@ npm install -g @observeone/cli
27
28
  obs export
28
29
  ```
29
30
 
30
- 3. **Manage a monitor**
31
+ 4. **Manage a monitor**
31
32
  ```bash
32
33
  obs monitor create --name "My Website" --url "https://example.com" --interval "*/5 * * * *"
33
34
  obs monitor list
@@ -35,6 +36,18 @@ npm install -g @observeone/cli
35
36
 
36
37
  ---
37
38
 
39
+ ## Configuration Priority
40
+
41
+ The CLI resolves configuration settings in the following order (highest to lowest priority):
42
+
43
+ 1. **CLI Flags**: `--api-key`, `--api-url` passed directly to a command.
44
+ 2. **Environment Variables**: `OBS_API_KEY`, `OBS_API_URL`.
45
+ 3. **Local Config File**: `.obs.config.json` in the current working directory (created via `obs init`).
46
+ 4. **Global Store**: Global OS configuration (saved after `obs login`).
47
+ 5. **Defaults**: Internal default values.
48
+
49
+ ---
50
+
38
51
  ## Config-as-Code (Declarative Workflow)
39
52
 
40
53
  ObserveOne supports an Infrastructure-as-Code (IaC) workflow using JSON. You can define all your monitors, API checks, and heartbeats in a single `obs.json` file and sync them to your account.
@@ -65,6 +78,7 @@ obs apply -f my-stack.json
65
78
  "monitors": [
66
79
  {
67
80
  "name": "Production Website",
81
+ "description": "Main landing page monitor",
68
82
  "url": "https://example.com",
69
83
  "interval": "*/5 * * * *",
70
84
  "alert_on_failure": true
@@ -80,7 +94,8 @@ obs apply -f my-stack.json
80
94
  "heartbeats": [
81
95
  {
82
96
  "name": "Database Backup Job",
83
- "period": 86400
97
+ "period": 86400,
98
+ "grace_period": 3600
84
99
  }
85
100
  ]
86
101
  }
@@ -93,7 +108,6 @@ obs apply -f my-stack.json
93
108
  You can manually create, read, update, delete, and toggle individual resources directly from the terminal.
94
109
 
95
110
  ### URL Monitors
96
- Manage basic HTTP ping monitors.
97
111
  ```bash
98
112
  obs monitor create --name "Frontend" --url "https://example.com" --interval "*/5 * * * *"
99
113
  obs monitor list
@@ -104,7 +118,6 @@ obs monitor delete <id> -y
104
118
  ```
105
119
 
106
120
  ### API Checks
107
- Manage complex API health checks.
108
121
  ```bash
109
122
  obs check create --name "Auth API" --url "https://api.example.com/auth" --method "POST"
110
123
  obs check list
@@ -114,51 +127,39 @@ obs check delete <id> -y
114
127
  ```
115
128
 
116
129
  ### Heartbeats (Cron Monitoring)
117
- Manage heartbeat checks (for monitoring background jobs or cron tasks).
118
130
  ```bash
119
- obs heartbeat create --name "Daily Backup" --period 86400
131
+ obs heartbeat create --name "Daily Backup" --period 86400 --grace 3600
120
132
  obs heartbeat list
121
133
  obs heartbeat update <id> --period 43200
122
134
  obs heartbeat toggle <id>
123
135
  obs heartbeat delete <id> -y
124
136
  ```
125
137
 
126
- ### AI Browser Checks
138
+ ---
139
+
140
+ ## AI Browser Checks
141
+
127
142
  Manage and execute intelligent Playwright-driven browser tests using natural language prompts.
128
- ```bash
129
- obs ai-check create --name "Login Flow" --url "https://app.com" --prompt "Login with test@example.com"
130
- obs ai-check list
131
- obs ai-check get <id>
132
- obs ai-check delete <id> -y
133
- ```
134
143
 
135
- #### Running AI Checks
136
- You can execute pre-configured checks or run them "ad-hoc" on the fly.
137
144
  ```bash
138
- # Run an existing test by name or ID
139
- obs ai-check run "Login Flow"
140
- obs ai-check run 123
145
+ # Run an existing test and output JUnit report for CI
146
+ obs ai-check run "Login Flow" --reporter junit
141
147
 
142
- # Run multiple tests sequentially
143
- obs ai-check run test1 test2 test3
148
+ # Run multiple tests and output strict JSON for AI Agents
149
+ obs ai-check run test1 test2 --reporter json
144
150
 
145
- # Run an ad-hoc test without saving it to the database
146
- obs ai-check run --adhoc --url https://example.com --prompt "Verify the hero section exists"
151
+ # Run an ad-hoc test without saving it
152
+ obs ai-check run --adhoc --url https://example.com --prompt "Verify login section exists"
147
153
  ```
148
154
 
149
155
  ---
150
156
 
151
157
  ## AI Agent Integration (Headless Mode)
152
158
 
153
- The `obs` CLI is explicitly designed to be used by AI coding agents (like Cursor, GitHub Copilot, Claude Code, or custom bots).
159
+ The `obs` CLI is explicitly designed to be used by AI coding agents.
154
160
 
155
161
  ### The `--json` Flag
156
- Append `--json` to **any** command. The CLI will automatically suppress all human-readable output (chalk colors, loading spinners, raw logs) and return a strict, machine-readable `JsonEnvelope`.
157
-
158
- ```bash
159
- obs monitor list --json
160
- obs apply -f my-stack.json --json
161
- ```
162
+ Append `--json` to **any** command. The CLI will automatically suppress all human-readable output and return a strict, machine-readable `JsonEnvelope`.
162
163
 
163
164
  **Guaranteed Agent Response Schema:**
164
165
  ```json
@@ -170,42 +171,25 @@ obs apply -f my-stack.json --json
170
171
  }
171
172
  }
172
173
  ```
173
- *(If an error occurs, `status` will be `"ERROR"` and the envelope will contain a strict `error` object, preventing the agent's JSON parser from crashing).*
174
-
175
- ### Headless Authentication & Account Setup
176
- Agents can create accounts and authenticate securely using environment variables without interactive browser prompts.
177
174
 
178
- #### Account Signup
179
- ```bash
180
- # Create a secure account for automated bots (Rate-limited)
181
- obs signup
182
- ```
183
-
184
- #### Headless Login
175
+ ### Headless Login
185
176
  Agents can authenticate securely using existing credentials:
186
177
  ```bash
187
178
  export OBS_EMAIL="agent@company.com"
188
179
  export OBS_PASSWORD="secure-password"
189
-
190
- # Automatically provisions and saves an API key to local config
191
180
  obs login --headless
192
181
  ```
193
182
 
194
- Alternatively, inject an existing API key directly into the environment:
195
- ```bash
196
- export OBS_API_KEY="your_api_key_here"
197
- ```
198
-
199
183
  ---
200
184
 
201
- ## Global Configuration
185
+ ## Update Notifications
202
186
 
203
- Available for all commands:
204
- ```bash
205
- obs <command> [options]
206
- ```
187
+ The CLI includes a non-blocking background update service that checks for newer versions on npm. If an update is available, a notification will be displayed at the start of your command output. This check is automatically disabled in `--json` mode.
188
+
189
+ ---
190
+
191
+ ## Global Options
207
192
 
208
- **Options:**
209
193
  - `-v, --verbose` - Enable verbose output and stack traces
210
194
  - `--json` - Output in strict JSON format
211
195
  - `--api-url <url>` - Override API URL
@@ -213,14 +197,6 @@ obs <command> [options]
213
197
  - `--version` - Show version number
214
198
  - `--help` - Show help
215
199
 
216
- ### Environment Variables
217
- ```bash
218
- export OBS_API_URL=https://api.observeone.com
219
- export OBS_API_KEY=your-api-key
220
- export OBS_VERBOSE=true
221
- export OBS_JSON_OUTPUT=true
222
- ```
223
-
224
200
  ## License
225
201
  MIT
226
202
 
package/dist/README.md CHANGED
@@ -19,6 +19,7 @@ npm install -g @observeone/cli
19
19
 
20
20
  2. **Initialize Workspace**
21
21
  ```bash
22
+ # Creates local .obs.config.json
22
23
  obs init
23
24
  ```
24
25
 
@@ -27,7 +28,7 @@ npm install -g @observeone/cli
27
28
  obs export
28
29
  ```
29
30
 
30
- 3. **Manage a monitor**
31
+ 4. **Manage a monitor**
31
32
  ```bash
32
33
  obs monitor create --name "My Website" --url "https://example.com" --interval "*/5 * * * *"
33
34
  obs monitor list
@@ -35,6 +36,18 @@ npm install -g @observeone/cli
35
36
 
36
37
  ---
37
38
 
39
+ ## Configuration Priority
40
+
41
+ The CLI resolves configuration settings in the following order (highest to lowest priority):
42
+
43
+ 1. **CLI Flags**: `--api-key`, `--api-url` passed directly to a command.
44
+ 2. **Environment Variables**: `OBS_API_KEY`, `OBS_API_URL`.
45
+ 3. **Local Config File**: `.obs.config.json` in the current working directory (created via `obs init`).
46
+ 4. **Global Store**: Global OS configuration (saved after `obs login`).
47
+ 5. **Defaults**: Internal default values.
48
+
49
+ ---
50
+
38
51
  ## Config-as-Code (Declarative Workflow)
39
52
 
40
53
  ObserveOne supports an Infrastructure-as-Code (IaC) workflow using JSON. You can define all your monitors, API checks, and heartbeats in a single `obs.json` file and sync them to your account.
@@ -65,6 +78,7 @@ obs apply -f my-stack.json
65
78
  "monitors": [
66
79
  {
67
80
  "name": "Production Website",
81
+ "description": "Main landing page monitor",
68
82
  "url": "https://example.com",
69
83
  "interval": "*/5 * * * *",
70
84
  "alert_on_failure": true
@@ -80,7 +94,8 @@ obs apply -f my-stack.json
80
94
  "heartbeats": [
81
95
  {
82
96
  "name": "Database Backup Job",
83
- "period": 86400
97
+ "period": 86400,
98
+ "grace_period": 3600
84
99
  }
85
100
  ]
86
101
  }
@@ -93,7 +108,6 @@ obs apply -f my-stack.json
93
108
  You can manually create, read, update, delete, and toggle individual resources directly from the terminal.
94
109
 
95
110
  ### URL Monitors
96
- Manage basic HTTP ping monitors.
97
111
  ```bash
98
112
  obs monitor create --name "Frontend" --url "https://example.com" --interval "*/5 * * * *"
99
113
  obs monitor list
@@ -104,7 +118,6 @@ obs monitor delete <id> -y
104
118
  ```
105
119
 
106
120
  ### API Checks
107
- Manage complex API health checks.
108
121
  ```bash
109
122
  obs check create --name "Auth API" --url "https://api.example.com/auth" --method "POST"
110
123
  obs check list
@@ -114,51 +127,39 @@ obs check delete <id> -y
114
127
  ```
115
128
 
116
129
  ### Heartbeats (Cron Monitoring)
117
- Manage heartbeat checks (for monitoring background jobs or cron tasks).
118
130
  ```bash
119
- obs heartbeat create --name "Daily Backup" --period 86400
131
+ obs heartbeat create --name "Daily Backup" --period 86400 --grace 3600
120
132
  obs heartbeat list
121
133
  obs heartbeat update <id> --period 43200
122
134
  obs heartbeat toggle <id>
123
135
  obs heartbeat delete <id> -y
124
136
  ```
125
137
 
126
- ### AI Browser Checks
138
+ ---
139
+
140
+ ## AI Browser Checks
141
+
127
142
  Manage and execute intelligent Playwright-driven browser tests using natural language prompts.
128
- ```bash
129
- obs ai-check create --name "Login Flow" --url "https://app.com" --prompt "Login with test@example.com"
130
- obs ai-check list
131
- obs ai-check get <id>
132
- obs ai-check delete <id> -y
133
- ```
134
143
 
135
- #### Running AI Checks
136
- You can execute pre-configured checks or run them "ad-hoc" on the fly.
137
144
  ```bash
138
- # Run an existing test by name or ID
139
- obs ai-check run "Login Flow"
140
- obs ai-check run 123
145
+ # Run an existing test and output JUnit report for CI
146
+ obs ai-check run "Login Flow" --reporter junit
141
147
 
142
- # Run multiple tests sequentially
143
- obs ai-check run test1 test2 test3
148
+ # Run multiple tests and output strict JSON for AI Agents
149
+ obs ai-check run test1 test2 --reporter json
144
150
 
145
- # Run an ad-hoc test without saving it to the database
146
- obs ai-check run --adhoc --url https://example.com --prompt "Verify the hero section exists"
151
+ # Run an ad-hoc test without saving it
152
+ obs ai-check run --adhoc --url https://example.com --prompt "Verify login section exists"
147
153
  ```
148
154
 
149
155
  ---
150
156
 
151
157
  ## AI Agent Integration (Headless Mode)
152
158
 
153
- The `obs` CLI is explicitly designed to be used by AI coding agents (like Cursor, GitHub Copilot, Claude Code, or custom bots).
159
+ The `obs` CLI is explicitly designed to be used by AI coding agents.
154
160
 
155
161
  ### The `--json` Flag
156
- Append `--json` to **any** command. The CLI will automatically suppress all human-readable output (chalk colors, loading spinners, raw logs) and return a strict, machine-readable `JsonEnvelope`.
157
-
158
- ```bash
159
- obs monitor list --json
160
- obs apply -f my-stack.json --json
161
- ```
162
+ Append `--json` to **any** command. The CLI will automatically suppress all human-readable output and return a strict, machine-readable `JsonEnvelope`.
162
163
 
163
164
  **Guaranteed Agent Response Schema:**
164
165
  ```json
@@ -170,42 +171,25 @@ obs apply -f my-stack.json --json
170
171
  }
171
172
  }
172
173
  ```
173
- *(If an error occurs, `status` will be `"ERROR"` and the envelope will contain a strict `error` object, preventing the agent's JSON parser from crashing).*
174
-
175
- ### Headless Authentication & Account Setup
176
- Agents can create accounts and authenticate securely using environment variables without interactive browser prompts.
177
174
 
178
- #### Account Signup
179
- ```bash
180
- # Create a secure account for automated bots (Rate-limited)
181
- obs signup
182
- ```
183
-
184
- #### Headless Login
175
+ ### Headless Login
185
176
  Agents can authenticate securely using existing credentials:
186
177
  ```bash
187
178
  export OBS_EMAIL="agent@company.com"
188
179
  export OBS_PASSWORD="secure-password"
189
-
190
- # Automatically provisions and saves an API key to local config
191
180
  obs login --headless
192
181
  ```
193
182
 
194
- Alternatively, inject an existing API key directly into the environment:
195
- ```bash
196
- export OBS_API_KEY="your_api_key_here"
197
- ```
198
-
199
183
  ---
200
184
 
201
- ## Global Configuration
185
+ ## Update Notifications
202
186
 
203
- Available for all commands:
204
- ```bash
205
- obs <command> [options]
206
- ```
187
+ The CLI includes a non-blocking background update service that checks for newer versions on npm. If an update is available, a notification will be displayed at the start of your command output. This check is automatically disabled in `--json` mode.
188
+
189
+ ---
190
+
191
+ ## Global Options
207
192
 
208
- **Options:**
209
193
  - `-v, --verbose` - Enable verbose output and stack traces
210
194
  - `--json` - Output in strict JSON format
211
195
  - `--api-url <url>` - Override API URL
@@ -213,14 +197,6 @@ obs <command> [options]
213
197
  - `--version` - Show version number
214
198
  - `--help` - Show help
215
199
 
216
- ### Environment Variables
217
- ```bash
218
- export OBS_API_URL=https://api.observeone.com
219
- export OBS_API_KEY=your-api-key
220
- export OBS_VERBOSE=true
221
- export OBS_JSON_OUTPUT=true
222
- ```
223
-
224
200
  ## License
225
201
  MIT
226
202
 
@@ -1 +1 @@
1
- {"version":3,"file":"ai-check.d.ts","sourceRoot":"","sources":["../../src/commands/ai-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAMnE;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,cAAc,EAC7B,SAAS,EAAE,UAAU,EACrB,aAAa,EAAE,cAAc,GAC5B,OAAO,CA+QT"}
1
+ {"version":3,"file":"ai-check.d.ts","sourceRoot":"","sources":["../../src/commands/ai-check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAqBnE;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,cAAc,EAC7B,SAAS,EAAE,UAAU,EACrB,aAAa,EAAE,cAAc,GAC5B,OAAO,CAyRT"}
@@ -69,7 +69,9 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
69
69
  .option('-f, --format <format>', 'Output format (table, json)', 'table')
70
70
  .option('-j, --json', 'Output in JSON format')
71
71
  .action(async (options) => {
72
- if (process.env.OBS_JSON_OUTPUT === 'true' || options.format === 'json' || options.json) {
72
+ if (process.env.OBS_JSON_OUTPUT === 'true' ||
73
+ options.format === 'json' ||
74
+ options.json === true) {
73
75
  outputService.enableJsonMode();
74
76
  }
75
77
  try {
@@ -80,7 +82,9 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
80
82
  }
81
83
  outputService.progress('Fetching AI checks...');
82
84
  const tests = await apiClient.getTests();
83
- if (process.env.OBS_JSON_OUTPUT === 'true' || options.format === 'json' || options.json) {
85
+ if (process.env.OBS_JSON_OUTPUT === 'true' ||
86
+ options.format === 'json' ||
87
+ options.json === true) {
84
88
  outputService.formatJsonOutput(tests);
85
89
  }
86
90
  else {
@@ -98,7 +102,7 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
98
102
  .description('Get details of an AI browser check')
99
103
  .option('-j, --json', 'Output in JSON format')
100
104
  .action(async (id, options) => {
101
- if (process.env.OBS_JSON_OUTPUT === 'true' || options.json) {
105
+ if (process.env.OBS_JSON_OUTPUT === 'true' || options.json === true) {
102
106
  outputService.enableJsonMode();
103
107
  }
104
108
  try {
@@ -135,7 +139,7 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
135
139
  .option('-p, --prompt <prompt>', 'Test prompt')
136
140
  .option('-j, --json', 'Output in JSON format')
137
141
  .action(async (options) => {
138
- if (process.env.OBS_JSON_OUTPUT === 'true' || options.json) {
142
+ if (process.env.OBS_JSON_OUTPUT === 'true' || options.json === true) {
139
143
  outputService.enableJsonMode();
140
144
  }
141
145
  try {
@@ -144,7 +148,9 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
144
148
  outputService.error('Not authenticated. Please run "obs login" first.');
145
149
  process.exit(1);
146
150
  }
147
- let { name, url, prompt } = options;
151
+ let name = options.name;
152
+ let url = options.url;
153
+ let prompt = options.prompt;
148
154
  if (!name || !url || !prompt) {
149
155
  const answers = await inquirer.prompt([
150
156
  {
@@ -183,9 +189,9 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
183
189
  }
184
190
  outputService.progress('Creating AI browser check...');
185
191
  const newTest = await apiClient.createTest({
186
- name,
187
- url,
188
- prompt,
192
+ name: name,
193
+ url: url,
194
+ prompt: prompt,
189
195
  description: 'Created via CLI',
190
196
  });
191
197
  if (process.env.OBS_JSON_OUTPUT === 'true') {
@@ -207,7 +213,7 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
207
213
  .option('-y, --yes', 'Skip confirmation prompt')
208
214
  .option('-j, --json', 'Output in JSON format')
209
215
  .action(async (id, options) => {
210
- if (process.env.OBS_JSON_OUTPUT === 'true' || options.json) {
216
+ if (process.env.OBS_JSON_OUTPUT === 'true' || options.json === true) {
211
217
  outputService.enableJsonMode();
212
218
  }
213
219
  try {
@@ -254,7 +260,7 @@ export function createAiCheckCommand(configService, apiClient, outputService) {
254
260
  */
255
261
  async function runAdhocTest(apiClient, outputService, configService, options, timeout, results, shouldWait, isJson) {
256
262
  const spinner = isJson
257
- ? { start: () => { }, succeed: () => { }, fail: () => { } }
263
+ ? { start: () => { }, succeed: (_msg) => { }, fail: (_msg) => { } }
258
264
  : ora('Running ad-hoc test...').start();
259
265
  try {
260
266
  const result = await apiClient.executeAdhocTest({
@@ -278,9 +284,9 @@ async function runAdhocTest(apiClient, outputService, configService, options, ti
278
284
  /**
279
285
  * Run named tests
280
286
  */
281
- async function runNamedTests(apiClient, outputService, configService, testNames, options, timeout, results, shouldWait, isJson) {
287
+ async function runNamedTests(apiClient, _outputService, configService, testNames, options, timeout, results, shouldWait, isJson) {
282
288
  const spinner = isJson
283
- ? { start: () => { }, succeed: () => { }, fail: () => { } }
289
+ ? { start: () => { }, succeed: (_msg) => { }, fail: (_msg) => { } }
284
290
  : ora('Fetching test details...').start();
285
291
  try {
286
292
  const tests = await apiClient.getTests();
@@ -304,7 +310,7 @@ async function runNamedTests(apiClient, outputService, configService, testNames,
304
310
  // Execute each test
305
311
  for (const test of testsToRun) {
306
312
  const testSpinner = isJson
307
- ? { start: () => { }, succeed: () => { }, fail: () => { } }
313
+ ? { start: () => { }, succeed: (_msg) => { }, fail: (_msg) => { } }
308
314
  : ora(`Running test: ${test.name}`).start();
309
315
  try {
310
316
  const result = await apiClient.executeTest(test.id);
@@ -355,7 +361,7 @@ async function streamTestProgress(configService, result, testName, options, time
355
361
  if (message.type === 'step_update' && message.step) {
356
362
  stepCounter++;
357
363
  const step = message.step;
358
- if (!silent) {
364
+ if (!silent && renderer && logger) {
359
365
  if (message.screenshot) {
360
366
  renderer.addScreenshot();
361
367
  logger.writeScreenshot(stepCounter);
@@ -365,14 +371,14 @@ async function streamTestProgress(configService, result, testName, options, time
365
371
  }
366
372
  }
367
373
  else if (message.type === 'screenshot') {
368
- if (!silent) {
374
+ if (!silent && renderer && logger) {
369
375
  renderer.addScreenshot();
370
376
  logger.writeScreenshot(stepCounter);
371
377
  }
372
378
  }
373
379
  else if (message.type === 'complete' || message.type === 'task_completed') {
374
380
  const status = message.status === 'failed' ? 'failed' : 'success';
375
- if (!silent) {
381
+ if (!silent && renderer && logger) {
376
382
  renderer.complete(status, message.message);
377
383
  logger.writeComplete(status, message.message);
378
384
  }
@@ -386,13 +392,13 @@ async function streamTestProgress(configService, result, testName, options, time
386
392
  };
387
393
  completed = true;
388
394
  sseClient.close();
389
- if (!silent) {
395
+ if (!silent && logger) {
390
396
  logger.close();
391
397
  console.log(chalk.gray(`\nDetailed logs: ${logger.getPath()}`));
392
398
  }
393
399
  }
394
400
  else if (message.type === 'error') {
395
- if (!silent) {
401
+ if (!silent && renderer && logger) {
396
402
  renderer.error(message.message || 'Test failed');
397
403
  logger.writeComplete('failed', message.message);
398
404
  }
@@ -403,23 +409,24 @@ async function streamTestProgress(configService, result, testName, options, time
403
409
  };
404
410
  completed = true;
405
411
  sseClient.close();
406
- if (!silent) {
412
+ if (!silent && logger) {
407
413
  logger.close();
408
414
  }
409
415
  }
410
416
  }, (error) => {
411
417
  if (!completed) {
412
- if (!silent) {
413
- renderer.error(`Connection error: ${error.message}`);
414
- logger.writeComplete('failed', `Connection error: ${error.message}`);
418
+ const err = error;
419
+ if (!silent && renderer && logger) {
420
+ renderer.error(`Connection error: ${err.message}`);
421
+ logger.writeComplete('failed', `Connection error: ${err.message}`);
415
422
  }
416
423
  results[results.length - 1] = {
417
424
  ...result,
418
425
  status: 'FAILED',
419
- message: `Connection error: ${error.message}`,
426
+ message: `Connection error: ${err.message}`,
420
427
  };
421
428
  sseClient.close();
422
- if (!silent) {
429
+ if (!silent && logger) {
423
430
  logger.close();
424
431
  }
425
432
  completed = true;
@@ -436,7 +443,7 @@ async function streamTestProgress(configService, result, testName, options, time
436
443
  setTimeout(() => {
437
444
  if (!completed) {
438
445
  clearInterval(checkInterval);
439
- if (!silent) {
446
+ if (!silent && renderer) {
440
447
  renderer.error('Test execution timed out');
441
448
  }
442
449
  results[results.length - 1] = {
@@ -445,7 +452,7 @@ async function streamTestProgress(configService, result, testName, options, time
445
452
  message: 'Test execution timed out',
446
453
  };
447
454
  sseClient.close();
448
- if (!silent) {
455
+ if (!silent && logger) {
449
456
  logger.close();
450
457
  }
451
458
  resolve();
@@ -507,11 +514,11 @@ function generateJUnitReport(results, outputService) {
507
514
  tests: results.length,
508
515
  failures: results.filter((r) => r.status === 'FAILED').length,
509
516
  errors: 0,
510
- time: results.reduce((total, r) => total + (r.duration || 0), 0) / 1000,
517
+ time: (results.reduce((total, r) => total + (r.duration || 0), 0) / 1000).toString(),
511
518
  testCases: results.map((result, index) => ({
512
519
  name: `Test ${index + 1}`,
513
520
  classname: 'observeone.test',
514
- time: (result.duration || 0) / 1000,
521
+ time: ((result.duration || 0) / 1000).toString(),
515
522
  status: result.status === 'SUCCESS' ? 'passed' : 'failed',
516
523
  failure: result.status === 'FAILED'
517
524
  ? {