@ishlabs/cli 0.26.0 → 0.26.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.
- package/dist/commands/doctor.d.ts +16 -0
- package/dist/commands/doctor.js +34 -9
- package/dist/commands/iteration.js +23 -5
- package/dist/commands/study-participant.js +1 -1
- package/dist/commands/study-run.js +26 -1
- package/dist/commands/study-screenshots.js +38 -5
- package/dist/lib/api-client.d.ts +3 -0
- package/dist/lib/api-client.js +6 -1
- package/dist/lib/docs.js +15 -3
- package/dist/lib/local-sim/actions.d.ts +18 -0
- package/dist/lib/local-sim/actions.js +30 -0
- package/dist/lib/local-sim/adb.d.ts +23 -0
- package/dist/lib/local-sim/adb.js +106 -16
- package/dist/lib/local-sim/android.d.ts +7 -1
- package/dist/lib/local-sim/android.js +16 -1
- package/dist/lib/local-sim/device.d.ts +19 -0
- package/dist/lib/local-sim/ios.d.ts +7 -1
- package/dist/lib/local-sim/ios.js +16 -1
- package/dist/lib/local-sim/loop.js +133 -26
- package/dist/lib/local-sim/simctl.d.ts +15 -0
- package/dist/lib/local-sim/simctl.js +41 -1
- package/dist/lib/local-sim/types.d.ts +11 -2
- package/dist/lib/paths.d.ts +6 -0
- package/dist/lib/paths.js +9 -0
- package/dist/lib/report-readiness.d.ts +44 -0
- package/dist/lib/report-readiness.js +74 -0
- package/dist/lib/skill-content.js +2 -0
- package/package.json +1 -1
|
@@ -12,10 +12,12 @@ export interface LocalSimInitRequest {
|
|
|
12
12
|
iteration_id: string;
|
|
13
13
|
}
|
|
14
14
|
export interface IterationDetails {
|
|
15
|
-
url
|
|
15
|
+
url?: string;
|
|
16
16
|
platform: string;
|
|
17
17
|
screen_format: "desktop" | "mobile_portrait";
|
|
18
18
|
locale?: string;
|
|
19
|
+
/** Native (ios/android): the app target to install/launch (bundle id / package / path). */
|
|
20
|
+
app_artifact?: string;
|
|
19
21
|
}
|
|
20
22
|
export interface LocalSimInitResponse {
|
|
21
23
|
participant_id: string;
|
|
@@ -221,6 +223,14 @@ export interface RecordInteraction {
|
|
|
221
223
|
assignment_status: AssignmentStatus;
|
|
222
224
|
tabs?: LocalTabInfo[];
|
|
223
225
|
}
|
|
226
|
+
export interface LocalSimInteractionRequest {
|
|
227
|
+
participant_id: string;
|
|
228
|
+
product_id: string;
|
|
229
|
+
interaction: RecordInteraction;
|
|
230
|
+
}
|
|
231
|
+
export interface LocalSimInteractionResponse {
|
|
232
|
+
interaction_id: string;
|
|
233
|
+
}
|
|
224
234
|
export interface AssignmentStatusUpdate {
|
|
225
235
|
assignment_id: string;
|
|
226
236
|
status: string;
|
|
@@ -229,7 +239,6 @@ export interface AssignmentStatusUpdate {
|
|
|
229
239
|
export interface LocalSimRecordRequest {
|
|
230
240
|
participant_id: string;
|
|
231
241
|
product_id: string;
|
|
232
|
-
interactions: RecordInteraction[];
|
|
233
242
|
final_status: string;
|
|
234
243
|
assignment_statuses: AssignmentStatusUpdate[];
|
|
235
244
|
}
|
package/dist/lib/paths.d.ts
CHANGED
|
@@ -20,4 +20,10 @@ export declare function cloudflaredBin(): string;
|
|
|
20
20
|
export declare function wdaDir(): string;
|
|
21
21
|
/** Stamp file recording which CLI/runner version the cached WDA bundle is for. */
|
|
22
22
|
export declare function wdaVersionFile(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Path to `adb` inside Google's standalone Android platform-tools, when we've
|
|
25
|
+
* fetched it into `binDir()` on demand (the zip unpacks a `platform-tools/`
|
|
26
|
+
* dir). Mirrors `cloudflaredBin()` / `wdaDir()`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function adbBin(): string;
|
|
23
29
|
export declare function connectLockPath(): string;
|
package/dist/lib/paths.js
CHANGED
|
@@ -46,6 +46,15 @@ export function wdaDir() {
|
|
|
46
46
|
export function wdaVersionFile() {
|
|
47
47
|
return path.join(wdaDir(), "VERSION");
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Path to `adb` inside Google's standalone Android platform-tools, when we've
|
|
51
|
+
* fetched it into `binDir()` on demand (the zip unpacks a `platform-tools/`
|
|
52
|
+
* dir). Mirrors `cloudflaredBin()` / `wdaDir()`.
|
|
53
|
+
*/
|
|
54
|
+
export function adbBin() {
|
|
55
|
+
const exe = process.platform === "win32" ? "adb.exe" : "adb";
|
|
56
|
+
return path.join(binDir(), "platform-tools", exe);
|
|
57
|
+
}
|
|
49
58
|
export function connectLockPath() {
|
|
50
59
|
return path.join(rootDir(), "connect.lock");
|
|
51
60
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort readiness reporting to the ish backend.
|
|
3
|
+
*
|
|
4
|
+
* After the CLI computes its native-simulation readiness checks (the same
|
|
5
|
+
* array `ish check <platform> --json` emits), we POST them to
|
|
6
|
+
* `${apiUrl}/api/v1/connect/device` so the ish web app can render a live
|
|
7
|
+
* native-readiness panel. This is the native analog of how `ish connect
|
|
8
|
+
* <port>` registers a cloudflare tunnel: a side-channel that tells the
|
|
9
|
+
* backend "this developer's machine is (or isn't) ready to drive a native
|
|
10
|
+
* iOS/Android simulation right now."
|
|
11
|
+
*
|
|
12
|
+
* Contract (must match the backend exactly):
|
|
13
|
+
*
|
|
14
|
+
* POST /api/v1/connect/device
|
|
15
|
+
* {
|
|
16
|
+
* "platform": "ios" | "android",
|
|
17
|
+
* "checks": [ {key,name,group,status,message?,fix?}, ... ],
|
|
18
|
+
* "overall": "pass" | "warn" | "fail" | "skip",
|
|
19
|
+
* "cli_version": "<package.json version>"
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* This is COMPLETELY best-effort. It never throws, never blocks the command,
|
|
23
|
+
* never writes to stdout, and silently returns when the user isn't logged in
|
|
24
|
+
* or is offline. The CLI's normal output and exit code are unaffected. The
|
|
25
|
+
* only side-channel is an optional stderr line under a `debug` flag, mirroring
|
|
26
|
+
* how connect.ts logs its own warnings.
|
|
27
|
+
*/
|
|
28
|
+
import type { GlobalOpts } from "./command-helpers.js";
|
|
29
|
+
import type { Check, CheckStatus } from "../commands/doctor.js";
|
|
30
|
+
/**
|
|
31
|
+
* POST the platform-scoped readiness checks to the backend. Best-effort:
|
|
32
|
+
* resolves auth + posts inside a single try/catch, swallowing every error.
|
|
33
|
+
*
|
|
34
|
+
* @param platform The native platform the checks were scoped to.
|
|
35
|
+
* @param checks The exact `runChecks()` array (already scoped to `platform`).
|
|
36
|
+
* @param overall The aggregate status (`overall(checks)`).
|
|
37
|
+
* @param globals Resolved CLI globals — used only for `--api-url` / `--dev`
|
|
38
|
+
* / `--token` resolution. Pass the command's `globals`.
|
|
39
|
+
* @param opts.debug When true, log a one-line failure note to stderr (off by
|
|
40
|
+
* default so the post is silent). Mirrors connect.ts.
|
|
41
|
+
*/
|
|
42
|
+
export declare function reportReadiness(platform: "ios" | "android", checks: Check[], overall: CheckStatus, globals: Pick<GlobalOpts, "apiUrl" | "dev" | "token" | "tokenFile">, opts?: {
|
|
43
|
+
debug?: boolean;
|
|
44
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort readiness reporting to the ish backend.
|
|
3
|
+
*
|
|
4
|
+
* After the CLI computes its native-simulation readiness checks (the same
|
|
5
|
+
* array `ish check <platform> --json` emits), we POST them to
|
|
6
|
+
* `${apiUrl}/api/v1/connect/device` so the ish web app can render a live
|
|
7
|
+
* native-readiness panel. This is the native analog of how `ish connect
|
|
8
|
+
* <port>` registers a cloudflare tunnel: a side-channel that tells the
|
|
9
|
+
* backend "this developer's machine is (or isn't) ready to drive a native
|
|
10
|
+
* iOS/Android simulation right now."
|
|
11
|
+
*
|
|
12
|
+
* Contract (must match the backend exactly):
|
|
13
|
+
*
|
|
14
|
+
* POST /api/v1/connect/device
|
|
15
|
+
* {
|
|
16
|
+
* "platform": "ios" | "android",
|
|
17
|
+
* "checks": [ {key,name,group,status,message?,fix?}, ... ],
|
|
18
|
+
* "overall": "pass" | "warn" | "fail" | "skip",
|
|
19
|
+
* "cli_version": "<package.json version>"
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* This is COMPLETELY best-effort. It never throws, never blocks the command,
|
|
23
|
+
* never writes to stdout, and silently returns when the user isn't logged in
|
|
24
|
+
* or is offline. The CLI's normal output and exit code are unaffected. The
|
|
25
|
+
* only side-channel is an optional stderr line under a `debug` flag, mirroring
|
|
26
|
+
* how connect.ts logs its own warnings.
|
|
27
|
+
*/
|
|
28
|
+
import { resolveApiUrl, resolveToken } from "./auth.js";
|
|
29
|
+
import { ApiClient } from "./api-client.js";
|
|
30
|
+
import pkg from "../../package.json" with { type: "json" };
|
|
31
|
+
/** Backend endpoint (relative to the `/api/v1` base ApiClient prepends). */
|
|
32
|
+
const DEVICE_ENDPOINT = "/connect/device";
|
|
33
|
+
/**
|
|
34
|
+
* POST the platform-scoped readiness checks to the backend. Best-effort:
|
|
35
|
+
* resolves auth + posts inside a single try/catch, swallowing every error.
|
|
36
|
+
*
|
|
37
|
+
* @param platform The native platform the checks were scoped to.
|
|
38
|
+
* @param checks The exact `runChecks()` array (already scoped to `platform`).
|
|
39
|
+
* @param overall The aggregate status (`overall(checks)`).
|
|
40
|
+
* @param globals Resolved CLI globals — used only for `--api-url` / `--dev`
|
|
41
|
+
* / `--token` resolution. Pass the command's `globals`.
|
|
42
|
+
* @param opts.debug When true, log a one-line failure note to stderr (off by
|
|
43
|
+
* default so the post is silent). Mirrors connect.ts.
|
|
44
|
+
*/
|
|
45
|
+
export async function reportReadiness(platform, checks, overall, globals, opts = {}) {
|
|
46
|
+
try {
|
|
47
|
+
const apiUrl = resolveApiUrl(globals.apiUrl, globals.dev);
|
|
48
|
+
// resolveToken throws when the user isn't logged in (or a network blip
|
|
49
|
+
// prevents an expired-token refresh) — that throw is caught below and we
|
|
50
|
+
// silently return, exactly as required for the offline / logged-out case.
|
|
51
|
+
const token = await resolveToken(globals.token, apiUrl, globals.tokenFile);
|
|
52
|
+
const client = new ApiClient({ apiUrl, token });
|
|
53
|
+
await client.post(DEVICE_ENDPOINT, {
|
|
54
|
+
platform,
|
|
55
|
+
checks,
|
|
56
|
+
overall,
|
|
57
|
+
cli_version: pkg.version,
|
|
58
|
+
},
|
|
59
|
+
// Tight timeout: `ish check` awaits this so the beacon lands before the
|
|
60
|
+
// process exits, but the panel POST must never stall the command. 2.5s
|
|
61
|
+
// is plenty on a healthy backend and bounds the worst case if the host
|
|
62
|
+
// is unreachable or hung.
|
|
63
|
+
{ timeout: 2_500 });
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
// Swallow everything. A logged-out user, an offline machine, an old
|
|
67
|
+
// backend without the endpoint, a 5xx — none of it should ever surface
|
|
68
|
+
// to the user or change the command's behavior.
|
|
69
|
+
if (opts.debug) {
|
|
70
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
71
|
+
console.error(`(readiness report skipped: ${reason})`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -230,6 +230,8 @@ To hand a study to someone **without an ish account** — a prospect, a stakehol
|
|
|
230
230
|
- **\`ish person create\` accepts inline flags** (mirrors \`person update\`): the file-only API (\`--file <path>\`) is preserved as an escape hatch but the common path is \`ish person create --name "X" --type ai --country US ...\` — \`--type\` defaults to \`ai\` when \`--file\` is omitted. See \`ish person create --help\` for the full inline-flag set including \`--household\` (MECE rule applies) and \`--accessibility-profile\`.
|
|
231
231
|
- **\`ish status\` now surfaces \`chat_endpoint\`** alongside \`workspace\`/\`study\`/\`ask\`. Stale or orphan active refs get a \`warning\` + \`hint\` field on the affected ref (instead of silently dropping the \`name\`). On \`workspace use <other>\`, the CLI cascade-clears \`study\`/\`ask\`/\`chat_endpoint\` (they belong to the previous workspace).
|
|
232
232
|
- **Share link URL host ≠ API host**: \`ish study share\` prints the backend-built \`share_url\` (the web frontend host). Use it verbatim — never reconstruct the URL from the API host or app URL; they differ. \`ish study unshare\` takes the **raw token** (from \`study share\` / \`study share --list\`), not a study id or alias.
|
|
233
|
+
- **Native app iterations (ios/android) name the app, not a URL**: \`ish iteration create --platform ios --app <bundle-id>\` stores the target as \`app_artifact\` (no URL). The iteration remembers it, so \`ish study run --local\` needs **no \`--app\` on reruns** (it defaults from the iteration). Pass \`--app <path-to.app|.apk>\` only to override with a fresh local build. \`--app\` is optional at create time (omit it for "chosen at run time"). Only \`browser\`/\`figma\` iterations require \`--url\`.
|
|
234
|
+
- **Local runs have no server-side screenshots**: \`ish study run --local\` (including ios/android) writes a per-step HTML debug report to \`~/.ish/debug/sim-*.html\` (path printed at the end of the run) instead of pushing screenshots to the server. \`ish study screenshots list\` on a local-only study finds none — open the debug report instead.
|
|
233
235
|
|
|
234
236
|
## When in doubt
|
|
235
237
|
|