@ishlabs/cli 0.8.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 (57) hide show
  1. package/LICENSE +6 -0
  2. package/README.md +69 -0
  3. package/dist/auth.d.ts +17 -0
  4. package/dist/auth.js +102 -0
  5. package/dist/commands/config.d.ts +5 -0
  6. package/dist/commands/config.js +82 -0
  7. package/dist/commands/iteration.d.ts +5 -0
  8. package/dist/commands/iteration.js +134 -0
  9. package/dist/commands/simulation.d.ts +10 -0
  10. package/dist/commands/simulation.js +647 -0
  11. package/dist/commands/study.d.ts +5 -0
  12. package/dist/commands/study.js +283 -0
  13. package/dist/commands/tester-profile.d.ts +5 -0
  14. package/dist/commands/tester-profile.js +109 -0
  15. package/dist/commands/tester.d.ts +5 -0
  16. package/dist/commands/tester.js +73 -0
  17. package/dist/commands/workspace.d.ts +5 -0
  18. package/dist/commands/workspace.js +133 -0
  19. package/dist/config.d.ts +13 -0
  20. package/dist/config.js +25 -0
  21. package/dist/connect.d.ts +4 -0
  22. package/dist/connect.js +573 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.js +89 -0
  25. package/dist/lib/alias-store.d.ts +49 -0
  26. package/dist/lib/alias-store.js +138 -0
  27. package/dist/lib/api-client.d.ts +58 -0
  28. package/dist/lib/api-client.js +177 -0
  29. package/dist/lib/auth.d.ts +8 -0
  30. package/dist/lib/auth.js +73 -0
  31. package/dist/lib/command-helpers.d.ts +28 -0
  32. package/dist/lib/command-helpers.js +131 -0
  33. package/dist/lib/local-sim/actions.d.ts +22 -0
  34. package/dist/lib/local-sim/actions.js +379 -0
  35. package/dist/lib/local-sim/browser.d.ts +63 -0
  36. package/dist/lib/local-sim/browser.js +332 -0
  37. package/dist/lib/local-sim/debug-report.d.ts +21 -0
  38. package/dist/lib/local-sim/debug-report.js +186 -0
  39. package/dist/lib/local-sim/debug.d.ts +44 -0
  40. package/dist/lib/local-sim/debug.js +103 -0
  41. package/dist/lib/local-sim/install.d.ts +25 -0
  42. package/dist/lib/local-sim/install.js +72 -0
  43. package/dist/lib/local-sim/loop.d.ts +60 -0
  44. package/dist/lib/local-sim/loop.js +526 -0
  45. package/dist/lib/local-sim/types.d.ts +232 -0
  46. package/dist/lib/local-sim/types.js +8 -0
  47. package/dist/lib/local-sim/upload.d.ts +6 -0
  48. package/dist/lib/local-sim/upload.js +24 -0
  49. package/dist/lib/output.d.ts +34 -0
  50. package/dist/lib/output.js +675 -0
  51. package/dist/lib/types.d.ts +179 -0
  52. package/dist/lib/types.js +12 -0
  53. package/dist/lib/upload.d.ts +47 -0
  54. package/dist/lib/upload.js +178 -0
  55. package/dist/upgrade.d.ts +1 -0
  56. package/dist/upgrade.js +94 -0
  57. package/package.json +43 -0
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Types for local browser simulation protocol.
3
+ *
4
+ * Aligned with backend contract (app/api/simulation/local/models.py).
5
+ * CLI captures observations locally, sends to Ish API for LLM reasoning,
6
+ * receives actions with node_ids, resolves elements locally via CDP.
7
+ */
8
+ export interface LocalSimInitRequest {
9
+ tester_id: string;
10
+ study_id: string;
11
+ product_id: string;
12
+ iteration_id: string;
13
+ }
14
+ export interface IterationDetails {
15
+ url: string;
16
+ platform: string;
17
+ screen_format: "desktop" | "mobile_portrait";
18
+ locale?: string;
19
+ }
20
+ export interface LocalSimInitResponse {
21
+ tester_id: string;
22
+ study_id: string;
23
+ product_id: string;
24
+ assignments: LocalSimAssignment[];
25
+ tester_background: Record<string, unknown> | null;
26
+ tester_language: string | null;
27
+ config: Record<string, unknown>;
28
+ context_values: ContextValue[];
29
+ max_interactions: number;
30
+ agent_model: string;
31
+ dom_model: string;
32
+ llm_provider: string;
33
+ iteration_details: IterationDetails | null;
34
+ }
35
+ export interface LocalSimAssignment {
36
+ id: string;
37
+ name: string;
38
+ instructions: string;
39
+ sequence: number;
40
+ }
41
+ export interface ContextValue {
42
+ name: string;
43
+ type: "var" | "secret";
44
+ value: string | null;
45
+ description?: string;
46
+ }
47
+ export interface HistoryEntry {
48
+ comment: string;
49
+ action_description: string;
50
+ location: string;
51
+ sentiment: string;
52
+ interacted_with: string | null;
53
+ is_user_instruction?: boolean;
54
+ }
55
+ export interface ForwardEntry {
56
+ type: string;
57
+ content: string;
58
+ }
59
+ export interface LocalSimStepRequest {
60
+ tester_id: string;
61
+ product_id: string;
62
+ assignment_name: string;
63
+ assignment_instructions: string;
64
+ screenshot: string;
65
+ accessibility_tree: string;
66
+ current_url: string;
67
+ screen_width: number;
68
+ screen_height: number;
69
+ interaction_count: number;
70
+ history: HistoryEntry[];
71
+ forwards: ForwardEntry[];
72
+ tester_background: Record<string, unknown> | null;
73
+ tester_language: string | null;
74
+ context_values: ContextValue[];
75
+ agent_model: string | null;
76
+ dom_model: string | null;
77
+ llm_provider: string | null;
78
+ user_instruction?: string | null;
79
+ }
80
+ export interface LocalStepAction {
81
+ type: string;
82
+ element_name: string | null;
83
+ element_description: string | null;
84
+ element_type: string | null;
85
+ node_id: string | null;
86
+ node_description: string | null;
87
+ value: string | null;
88
+ value_type: string | null;
89
+ mode: string | null;
90
+ submit: boolean | null;
91
+ direction: string | null;
92
+ amount: string | null;
93
+ count: number | null;
94
+ duration_ms: number | null;
95
+ thoughts: string | null;
96
+ }
97
+ /** Raw backend step response — output is nested, actions are separate. */
98
+ export interface LocalSimStepResponseRaw {
99
+ output: {
100
+ comment: string;
101
+ sentiment: string;
102
+ sentiment_valence?: number;
103
+ sentiment_intensity?: number;
104
+ current_location: string;
105
+ effort_seconds: number;
106
+ assignment_completed: boolean;
107
+ action: {
108
+ actions: Array<{
109
+ type: string;
110
+ element?: {
111
+ name: string;
112
+ type?: string;
113
+ description?: string;
114
+ };
115
+ value?: string;
116
+ value_type?: string;
117
+ mode?: string;
118
+ submit?: boolean;
119
+ direction?: string;
120
+ amount?: string;
121
+ count?: number;
122
+ duration_ms?: number;
123
+ thoughts?: string;
124
+ }>;
125
+ };
126
+ };
127
+ resolved_actions: LocalStepAction[];
128
+ loop_detected: boolean;
129
+ }
130
+ /** Normalized step response used by the loop. */
131
+ export interface LocalSimStepResponse {
132
+ comment: string;
133
+ sentiment: string;
134
+ sentiment_valence: number;
135
+ sentiment_intensity: number;
136
+ current_location: string;
137
+ effort_seconds: number;
138
+ assignment_completed: boolean;
139
+ actions: LocalStepAction[];
140
+ loop_detected: boolean;
141
+ }
142
+ export interface SentimentData {
143
+ label: string;
144
+ valence: number;
145
+ intensity: number;
146
+ }
147
+ export interface ActionData {
148
+ action_type: string;
149
+ element_label: string | null;
150
+ element_type: string | null;
151
+ coordinates: {
152
+ x: number;
153
+ y: number;
154
+ } | null;
155
+ data: Record<string, unknown> | null;
156
+ order: number;
157
+ }
158
+ export interface RecordInteraction {
159
+ step: number;
160
+ assignment_id: string;
161
+ screenshot_base64?: string;
162
+ screenshot_url?: string;
163
+ frame_version_id?: string;
164
+ timestamp_ms: number;
165
+ comment: string | null;
166
+ url: string | null;
167
+ sentiment: SentimentData;
168
+ actions: ActionData[];
169
+ current_location: string | null;
170
+ assignment_completed: boolean;
171
+ }
172
+ export interface AssignmentStatusUpdate {
173
+ assignment_id: string;
174
+ status: string;
175
+ step_count: number;
176
+ }
177
+ export interface LocalSimRecordRequest {
178
+ tester_id: string;
179
+ product_id: string;
180
+ interactions: RecordInteraction[];
181
+ final_status: string;
182
+ assignment_statuses: AssignmentStatusUpdate[];
183
+ }
184
+ export interface LocalSimRecordResponse {
185
+ tester_id: string;
186
+ interactions_created: number;
187
+ credits_consumed: number;
188
+ }
189
+ export interface ActionResult {
190
+ success: boolean;
191
+ elementName: string | null;
192
+ coordinates: {
193
+ x: number;
194
+ y: number;
195
+ } | null;
196
+ }
197
+ export interface LocalSimBrowserOptions {
198
+ headed: boolean;
199
+ slowMo?: number;
200
+ devtools?: boolean;
201
+ viewport: {
202
+ width: number;
203
+ height: number;
204
+ };
205
+ locale?: string;
206
+ screenFormat: "desktop" | "mobile_portrait";
207
+ }
208
+ /** Raw accessibility tree data stored for CDP node resolution. */
209
+ export interface TreeData {
210
+ simplified: string;
211
+ nodeMap: Map<string, {
212
+ backendNodeId: number;
213
+ frameIndex: number;
214
+ }>;
215
+ }
216
+ /**
217
+ * Session state cached from init, passed per step.
218
+ * Avoids DB lookups on the backend hot path.
219
+ */
220
+ export interface SessionState {
221
+ tester_id: string;
222
+ study_id: string;
223
+ product_id: string;
224
+ assignments: LocalSimAssignment[];
225
+ tester_background: Record<string, unknown> | null;
226
+ tester_language: string | null;
227
+ context_values: ContextValue[];
228
+ max_interactions: number;
229
+ agent_model: string;
230
+ dom_model: string;
231
+ llm_provider: string;
232
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Types for local browser simulation protocol.
3
+ *
4
+ * Aligned with backend contract (app/api/simulation/local/models.py).
5
+ * CLI captures observations locally, sends to Ish API for LLM reasoning,
6
+ * receives actions with node_ids, resolves elements locally via CDP.
7
+ */
8
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { ApiClient } from "../api-client.js";
2
+ export interface ScreenshotUploadResult {
3
+ screenshotUrl: string;
4
+ screenshotId: string;
5
+ }
6
+ export declare function uploadScreenshot(client: ApiClient, productId: string, jpegBuffer: Buffer): Promise<ScreenshotUploadResult>;
@@ -0,0 +1,24 @@
1
+ import { randomUUID } from "node:crypto";
2
+ export async function uploadScreenshot(client, productId, jpegBuffer) {
3
+ const screenshotId = randomUUID();
4
+ // Step 1: Get signed URL from backend
5
+ const resp = await client.localSimScreenshotUpload({
6
+ product_id: productId,
7
+ screenshot_id: screenshotId,
8
+ content_type: "image/jpeg",
9
+ });
10
+ // Step 2: PUT raw JPEG bytes directly to Supabase Storage
11
+ const putResp = await fetch(resp.upload_info.signed_upload_url, {
12
+ method: "PUT",
13
+ headers: {
14
+ "Content-Type": "image/jpeg",
15
+ "Content-Length": String(jpegBuffer.byteLength),
16
+ },
17
+ body: jpegBuffer,
18
+ signal: AbortSignal.timeout(30_000),
19
+ });
20
+ if (!putResp.ok) {
21
+ throw new Error(`Screenshot upload failed (HTTP ${putResp.status})`);
22
+ }
23
+ return { screenshotUrl: resp.screenshot_url, screenshotId };
24
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Output formatting utilities.
3
+ * Supports both human-readable and JSON output modes.
4
+ *
5
+ * JSON output is lean by default (strips UUIDs, nulls, timestamps) to
6
+ * minimize context-window usage for AI agent consumers. Use --verbose
7
+ * for the full API response.
8
+ */
9
+ /** Set by withClient() based on global flags. */
10
+ export declare function setVerbose(v: boolean): void;
11
+ export declare function setFields(fields?: string[]): void;
12
+ export declare function output(data: unknown, json: boolean): void;
13
+ export declare function outputList(rows: unknown[], json: boolean): void;
14
+ /**
15
+ * Error with valid options — used for content_type and similar validation.
16
+ * Surfaces valid_options in JSON so agents can self-correct.
17
+ */
18
+ export declare class ValidationError extends Error {
19
+ valid_options: string[];
20
+ constructor(message: string, valid_options: string[]);
21
+ }
22
+ export declare function outputError(err: unknown, json: boolean): void;
23
+ export declare function printTable(headers: string[], rows: string[][]): void;
24
+ export declare function printKeyValue(obj: Record<string, unknown>, indent?: string): void;
25
+ export declare function formatWorkspaceList(workspaces: Record<string, unknown>[], json: boolean): void;
26
+ export declare function formatWorkspaceDetail(workspace: Record<string, unknown>, json: boolean): void;
27
+ export declare function formatStudyList(studies: Record<string, unknown>[], json: boolean): void;
28
+ export declare function formatStudyDetail(study: Record<string, unknown>, json: boolean): void;
29
+ export declare function formatStudyResults(study: Record<string, unknown>, json: boolean): void;
30
+ export declare function formatIterationList(iterations: Record<string, unknown>[], json: boolean): void;
31
+ export declare function formatTesterDetail(tester: Record<string, unknown>, json: boolean): void;
32
+ export declare function formatTesterProfileList(profiles: unknown, json: boolean, limit?: number): void;
33
+ export declare function formatSimulationPoll(results: Record<string, unknown>[], json: boolean, isMedia?: boolean): void;
34
+ export declare function formatConfigList(configs: Record<string, unknown>[], json: boolean): void;