agent-device 0.13.2 → 0.14.0
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/README.md +68 -63
- package/android-snapshot-helper/README.md +75 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.0.apk +0 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.0.apk.sha256 +1 -0
- package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.14.0.manifest.json +17 -0
- package/bin/agent-device.mjs +6 -2
- package/dist/src/113.js +1 -1
- package/dist/src/1974.js +2 -2
- package/dist/src/221.js +4 -0
- package/dist/src/2301.js +1 -1
- package/dist/src/3918.js +29 -29
- package/dist/src/7847.js +1 -1
- package/dist/src/8161.js +3 -0
- package/dist/src/8656.js +1 -1
- package/dist/src/9152.js +1 -1
- package/dist/src/940.js +1 -0
- package/dist/src/9542.js +2 -2
- package/dist/src/9818.js +1 -1
- package/dist/src/989.js +1 -1
- package/dist/src/android-snapshot-helper.d.ts +181 -0
- package/dist/src/android-snapshot-helper.js +1 -0
- package/dist/src/index.d.ts +204 -1942
- package/dist/src/index.js +1 -1
- package/dist/src/internal/bin.js +440 -0
- package/dist/src/internal/companion-tunnel.js +1 -0
- package/dist/src/internal/daemon.js +45 -0
- package/dist/src/internal/update-check-entry.js +1 -0
- package/dist/src/metro.d.ts +5 -3
- package/dist/src/selectors.js +1 -1
- package/package.json +28 -24
- package/skills/agent-device/SKILL.md +20 -62
- package/skills/dogfood/SKILL.md +9 -168
- package/skills/react-devtools/SKILL.md +15 -31
- package/dist/src/4993.js +0 -1
- package/dist/src/5721.js +0 -1
- package/dist/src/7166.js +0 -1
- package/dist/src/8564.js +0 -3
- package/dist/src/9076.js +0 -1
- package/dist/src/backend.d.ts +0 -527
- package/dist/src/backend.js +0 -1
- package/dist/src/bin.js +0 -105
- package/dist/src/commands/index.d.ts +0 -1883
- package/dist/src/commands/index.js +0 -1
- package/dist/src/daemon.js +0 -43
- package/dist/src/metro-companion.js +0 -1
- package/dist/src/observability.d.ts +0 -91
- package/dist/src/observability.js +0 -1
- package/dist/src/testing/conformance.d.ts +0 -753
- package/dist/src/testing/conformance.js +0 -1
- package/dist/src/update-check-entry.js +0 -1
- package/skills/agent-device/references/bootstrap-install.md +0 -244
- package/skills/agent-device/references/coordinate-system.md +0 -28
- package/skills/agent-device/references/debugging.md +0 -138
- package/skills/agent-device/references/exploration.md +0 -362
- package/skills/agent-device/references/macos-desktop.md +0 -88
- package/skills/agent-device/references/remote-tenancy.md +0 -188
- package/skills/agent-device/references/verification.md +0 -134
- package/skills/dogfood/references/issue-taxonomy.md +0 -83
- package/skills/dogfood/templates/dogfood-report-template.md +0 -52
- package/skills/react-devtools/references/commands.md +0 -91
- package/skills/react-devtools/references/profiling.md +0 -74
- /package/dist/src/{bin.d.ts → internal/bin.d.ts} +0 -0
- /package/dist/src/{daemon.d.ts → internal/companion-tunnel.d.ts} +0 -0
- /package/dist/src/{metro-companion.d.ts → internal/daemon.d.ts} +0 -0
- /package/dist/src/{update-check-entry.d.ts → internal/update-check-entry.d.ts} +0 -0
package/dist/src/metro.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare function buildBundleUrl(baseUrl: string, platform: 'ios' | 'andro
|
|
|
4
4
|
|
|
5
5
|
export declare function buildIosRuntimeHints(baseUrl: string): MetroRuntimeHints;
|
|
6
6
|
|
|
7
|
-
declare type CompanionTunnelScope = {
|
|
7
|
+
export declare type CompanionTunnelScope = {
|
|
8
8
|
tenantId: string;
|
|
9
9
|
runId: string;
|
|
10
10
|
leaseId: string;
|
|
@@ -17,7 +17,7 @@ export declare type EnsureMetroTunnelOptions = {
|
|
|
17
17
|
serverBaseUrl: string;
|
|
18
18
|
bearerToken: string;
|
|
19
19
|
localBaseUrl: string;
|
|
20
|
-
bridgeScope:
|
|
20
|
+
bridgeScope: MetroBridgeScope;
|
|
21
21
|
launchUrl?: string;
|
|
22
22
|
profileKey?: string;
|
|
23
23
|
consumerKey?: string;
|
|
@@ -81,6 +81,8 @@ export declare type MetroBridgeRuntimePayload = {
|
|
|
81
81
|
launch_url?: string;
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
export declare type MetroBridgeScope = CompanionTunnelScope;
|
|
85
|
+
|
|
84
86
|
/** Re-export of {@link SessionRuntimeHints} under the Metro-specific alias used by public API consumers. */
|
|
85
87
|
export declare type MetroRuntimeHints = SessionRuntimeHints;
|
|
86
88
|
|
|
@@ -162,7 +164,7 @@ export declare type PrepareRemoteMetroOptions = {
|
|
|
162
164
|
publicBaseUrl?: string;
|
|
163
165
|
proxyBaseUrl?: string;
|
|
164
166
|
proxyBearerToken?: string;
|
|
165
|
-
bridgeScope?:
|
|
167
|
+
bridgeScope?: MetroBridgeScope;
|
|
166
168
|
launchUrl?: string;
|
|
167
169
|
profileKey?: string;
|
|
168
170
|
consumerKey?: string;
|
package/dist/src/selectors.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{findSelectorChainMatch,formatSelectorFailure,isNodeEditable,isNodeVisible,isSelectorToken,parseSelectorChain,resolveSelectorChain,tryParseSelectorChain}from"./
|
|
1
|
+
import"./7847.js";export{findSelectorChainMatch,formatSelectorFailure,isNodeEditable,isNodeVisible,isSelectorToken,parseSelectorChain,resolveSelectorChain,tryParseSelectorChain}from"./940.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Agent-driven CLI for mobile UI automation, network inspection, and performance diagnostics across iOS, Android, tvOS, and macOS.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Callstack",
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"url": "https://github.com/callstackincubator/agent-device/issues"
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
|
+
"packageManager": "pnpm@10.33.2",
|
|
16
17
|
"main": "dist/src/index.js",
|
|
17
18
|
"types": "dist/src/index.d.ts",
|
|
18
19
|
"exports": {
|
|
@@ -20,30 +21,14 @@
|
|
|
20
21
|
"import": "./dist/src/index.js",
|
|
21
22
|
"types": "./dist/src/index.d.ts"
|
|
22
23
|
},
|
|
23
|
-
"./commands": {
|
|
24
|
-
"import": "./dist/src/commands/index.js",
|
|
25
|
-
"types": "./dist/src/commands/index.d.ts"
|
|
26
|
-
},
|
|
27
|
-
"./backend": {
|
|
28
|
-
"import": "./dist/src/backend.js",
|
|
29
|
-
"types": "./dist/src/backend.d.ts"
|
|
30
|
-
},
|
|
31
24
|
"./io": {
|
|
32
25
|
"import": "./dist/src/io.js",
|
|
33
26
|
"types": "./dist/src/io.d.ts"
|
|
34
27
|
},
|
|
35
|
-
"./testing/conformance": {
|
|
36
|
-
"import": "./dist/src/testing/conformance.js",
|
|
37
|
-
"types": "./dist/src/testing/conformance.d.ts"
|
|
38
|
-
},
|
|
39
28
|
"./artifacts": {
|
|
40
29
|
"import": "./dist/src/artifacts.js",
|
|
41
30
|
"types": "./dist/src/artifacts.d.ts"
|
|
42
31
|
},
|
|
43
|
-
"./observability": {
|
|
44
|
-
"import": "./dist/src/observability.js",
|
|
45
|
-
"types": "./dist/src/observability.d.ts"
|
|
46
|
-
},
|
|
47
32
|
"./metro": {
|
|
48
33
|
"import": "./dist/src/metro.js",
|
|
49
34
|
"types": "./dist/src/metro.d.ts"
|
|
@@ -60,6 +45,10 @@
|
|
|
60
45
|
"import": "./dist/src/android-apps.js",
|
|
61
46
|
"types": "./dist/src/android-apps.d.ts"
|
|
62
47
|
},
|
|
48
|
+
"./android-snapshot-helper": {
|
|
49
|
+
"import": "./dist/src/android-snapshot-helper.js",
|
|
50
|
+
"types": "./dist/src/android-snapshot-helper.d.ts"
|
|
51
|
+
},
|
|
63
52
|
"./contracts": {
|
|
64
53
|
"import": "./dist/src/contracts.js",
|
|
65
54
|
"types": "./dist/src/contracts.d.ts"
|
|
@@ -74,7 +63,7 @@
|
|
|
74
63
|
}
|
|
75
64
|
},
|
|
76
65
|
"engines": {
|
|
77
|
-
"node": ">=22"
|
|
66
|
+
"node": ">=22.19"
|
|
78
67
|
},
|
|
79
68
|
"bin": {
|
|
80
69
|
"agent-device": "bin/agent-device.mjs"
|
|
@@ -87,19 +76,31 @@
|
|
|
87
76
|
"build:xcuitest:ios": "AGENT_DEVICE_XCUITEST_PLATFORM=ios AGENT_DEVICE_IOS_CLEAN_DERIVED=1 sh ./scripts/build-xcuitest-apple.sh",
|
|
88
77
|
"build:xcuitest:macos": "AGENT_DEVICE_XCUITEST_PLATFORM=macos sh ./scripts/build-xcuitest-apple.sh",
|
|
89
78
|
"build:xcuitest:tvos": "AGENT_DEVICE_XCUITEST_PLATFORM=tvos AGENT_DEVICE_IOS_CLEAN_DERIVED=1 sh ./scripts/build-xcuitest-apple.sh",
|
|
79
|
+
"build:android-snapshot-helper": "sh ./scripts/build-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") .tmp/android-snapshot-helper",
|
|
80
|
+
"package:android-snapshot-helper": "sh ./scripts/package-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") v$(node -p \"require('./package.json').version\") .tmp/android-snapshot-helper",
|
|
81
|
+
"package:android-snapshot-helper:npm": "rm -rf android-snapshot-helper/dist && sh ./scripts/package-android-snapshot-helper.sh $(node -p \"require('./package.json').version\") v$(node -p \"require('./package.json').version\") android-snapshot-helper/dist",
|
|
90
82
|
"build:macos-helper": "swift build -c release --package-path macos-helper",
|
|
91
83
|
"build:all": "pnpm build:node && pnpm build:xcuitest",
|
|
92
84
|
"ad": "node bin/agent-device.mjs",
|
|
93
85
|
"lint": "oxlint . --deny-warnings",
|
|
94
|
-
"format": "oxfmt --write src test skills package.json tsconfig.json .oxlintrc.json .oxfmtrc.json",
|
|
86
|
+
"format": "oxfmt --write src test skills package.json tsconfig.json tsconfig.lib.json rslib.config.ts vitest.config.ts .github/actions/setup-node-pnpm/action.yml .oxlintrc.json .oxfmtrc.json '!test/skillgym/.skillgym-results/**'",
|
|
87
|
+
"fallow": "fallow --summary",
|
|
88
|
+
"fallow:baseline": "(fallow dead-code --save-baseline fallow-baselines/dead-code.json --summary || true) && (fallow dupes --save-baseline fallow-baselines/dupes.json --summary || true) && (fallow health --save-baseline fallow-baselines/health.json --summary || true)",
|
|
89
|
+
"check:fallow": "fallow audit",
|
|
95
90
|
"check:quick": "pnpm lint && pnpm typecheck",
|
|
96
91
|
"check:tooling": "pnpm lint && pnpm typecheck && pnpm build",
|
|
97
92
|
"check:unit": "pnpm test:unit && pnpm test:smoke",
|
|
98
|
-
"check": "pnpm check:tooling && pnpm check:unit",
|
|
99
|
-
"prepack": "pnpm build:all",
|
|
93
|
+
"check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit",
|
|
94
|
+
"prepack": "pnpm build:all && pnpm package:android-snapshot-helper:npm",
|
|
100
95
|
"typecheck": "tsc -p tsconfig.json",
|
|
96
|
+
"test-app:install": "pnpm install --dir examples/test-app --ignore-workspace",
|
|
97
|
+
"test-app:start": "pnpm --dir examples/test-app start",
|
|
98
|
+
"test-app:ios": "pnpm --dir examples/test-app ios",
|
|
99
|
+
"test-app:android": "pnpm --dir examples/test-app android",
|
|
100
|
+
"test-app:typecheck": "pnpm --dir examples/test-app typecheck",
|
|
101
101
|
"test": "vitest run",
|
|
102
102
|
"test:unit": "vitest run",
|
|
103
|
+
"test:skillgym": "pnpm build && skillgym run ./test/skillgym/suites/agent-device-smoke-suite.ts --config ./test/skillgym/skillgym.config.ts",
|
|
103
104
|
"test:smoke": "node --test test/integration/smoke-*.test.ts",
|
|
104
105
|
"test:integration": "node --test test/integration/*.test.ts",
|
|
105
106
|
"test:replay:ios": "node --experimental-strip-types src/bin.ts test test/integration/replays/ios/simulator",
|
|
@@ -118,6 +119,8 @@
|
|
|
118
119
|
"!ios-runner/**/*.xcuserstate",
|
|
119
120
|
"macos-helper",
|
|
120
121
|
"!macos-helper/**/.build",
|
|
122
|
+
"android-snapshot-helper/dist",
|
|
123
|
+
"!android-snapshot-helper/dist/*.idsig",
|
|
121
124
|
"src/platforms/linux/atspi-dump.py",
|
|
122
125
|
"skills",
|
|
123
126
|
"README.md",
|
|
@@ -152,14 +155,15 @@
|
|
|
152
155
|
"pngjs": "^7.0.0"
|
|
153
156
|
},
|
|
154
157
|
"devDependencies": {
|
|
155
|
-
"
|
|
158
|
+
"vitest": "^4.1.2",
|
|
156
159
|
"@rslib/core": "0.20.1",
|
|
157
160
|
"@types/node": "^22.0.0",
|
|
158
161
|
"@types/pngjs": "^6.0.5",
|
|
162
|
+
"fallow": "^2.52.0",
|
|
159
163
|
"oxfmt": "^0.42.0",
|
|
160
164
|
"oxlint": "^1.57.0",
|
|
165
|
+
"skillgym": "^0.5.0",
|
|
161
166
|
"typescript": "^6.0.2",
|
|
162
|
-
"vite": "^8.0.7"
|
|
163
|
-
"vitest": "^4.1.2"
|
|
167
|
+
"vite": "^8.0.7"
|
|
164
168
|
}
|
|
165
169
|
}
|
|
@@ -1,76 +1,34 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-device
|
|
3
|
-
description: Automates
|
|
3
|
+
description: Automates Apple-platform apps (iOS, tvOS, macOS) and Android devices. Use when navigating apps, taking snapshots/screenshots, tapping, typing, scrolling, extracting UI info, collecting logs/network/perf evidence, or planning agent-device CLI commands.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# agent-device
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Router only. Private setup before using this skill:
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
```bash
|
|
11
|
+
agent-device --version
|
|
12
|
+
```
|
|
11
13
|
|
|
12
|
-
-
|
|
13
|
-
- Start deterministic. If the app name, package, device, or session is uncertain, load bootstrap and discover them before interacting.
|
|
14
|
-
- Use plain `snapshot` when the task is to verify what text or structure is currently visible on screen.
|
|
15
|
-
- Use `snapshot -i` only when you need interactive refs such as `@e3` for a requested action or targeted query. On iOS and Android, default snapshot output uses the same visible-first model: off-screen interactive content is exposed as discovery hints, not tappable refs.
|
|
16
|
-
- Prefer `diff snapshot` after a nearby mutation when you only need to know what changed.
|
|
17
|
-
- Avoid speculative mutations. You may take the smallest reversible UI action needed to unblock inspection or complete the requested task, such as dismissing a popup, closing an alert, or clearing an unintended surface.
|
|
18
|
-
- In React Native dev or debug builds, check early for visible warning or error overlays, tooltips, and toasts that can steal focus or intercept taps. If they are not part of the requested behavior, dismiss them and continue. If you saw them, report them in the final summary.
|
|
19
|
-
- In Metro-backed React Native dev loops, use `agent-device metro reload` for a JS app reload before falling back to `open <app> --relaunch`. It mirrors pressing `r` in the Metro terminal and preserves the native app process.
|
|
20
|
-
- Do not browse the web or use external sources unless the user explicitly asks.
|
|
21
|
-
- Re-snapshot after meaningful UI changes instead of reusing stale refs.
|
|
22
|
-
- Treat refs in default snapshot output as actionable-now, not durable identities. If a target appears only in an off-screen summary, use `scroll <direction>` and re-snapshot until the target is visible.
|
|
23
|
-
- Prefer `@ref` or selector targeting over raw coordinates.
|
|
24
|
-
- Ensure the correct target is pinned and an app session is open before interacting.
|
|
25
|
-
- Keep the loop short: `open` -> inspect/act -> verify if needed -> `close`.
|
|
14
|
+
Require `agent-device >= 0.13.4`; older CLIs lack these help topics. If older, run `npm install -g agent-device@latest`, recheck, then continue. If you cannot upgrade, stop and tell the user. Do not include version/upgrade commands in final plans.
|
|
26
15
|
|
|
27
|
-
|
|
16
|
+
Before your first agent-device command or plan, read the version-matched CLI guide:
|
|
28
17
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
4. Start with plain `snapshot` if the goal is to read or verify what is visible.
|
|
33
|
-
5. Escalate to `snapshot -i` only if you need refs for interactive exploration or a requested action.
|
|
34
|
-
6. Use `get`, `is`, or `find` before mutating the UI when a read-only command can answer the question.
|
|
35
|
-
7. End by capturing proof if needed, then `close`.
|
|
18
|
+
```bash
|
|
19
|
+
agent-device help workflow
|
|
20
|
+
```
|
|
36
21
|
|
|
37
|
-
|
|
22
|
+
Escalate only when relevant:
|
|
38
23
|
|
|
39
|
-
|
|
40
|
-
-
|
|
24
|
+
```bash
|
|
25
|
+
agent-device help debugging
|
|
26
|
+
agent-device help react-devtools
|
|
27
|
+
agent-device help remote
|
|
28
|
+
agent-device help macos
|
|
29
|
+
agent-device help dogfood
|
|
30
|
+
```
|
|
41
31
|
|
|
42
|
-
|
|
32
|
+
Default loop: `open -> snapshot/-i -> get/is/find or press/fill/scroll/wait -> verify -> close`.
|
|
43
33
|
|
|
44
|
-
|
|
45
|
-
- Use bootstrap to confirm or establish deterministic setup, especially in sandbox or cloud environments.
|
|
46
|
-
- Use exploration once the app session is open and stable.
|
|
47
|
-
- Load additional references only when their scope is needed.
|
|
48
|
-
|
|
49
|
-
## Decision rules
|
|
50
|
-
|
|
51
|
-
- Use plain `snapshot` when you need to verify whether text is visible.
|
|
52
|
-
- Use `snapshot -i` mainly for interactive exploration and choosing refs.
|
|
53
|
-
- Use `diff snapshot` for compact post-action verification; use `snapshot --diff` when that alias is easier to discover from snapshot help.
|
|
54
|
-
- Use `get`, `is`, or `find` when they can answer the question without changing UI state.
|
|
55
|
-
- Use `fill` to replace text.
|
|
56
|
-
- Use `type` to append text.
|
|
57
|
-
- Do not write `type @eN "text"`. Use `fill @eN "text"` to target a field directly, or `press @eN` then `type "text"` when the field already has focus and you want append semantics.
|
|
58
|
-
- If the on-screen keyboard blocks the next step, prefer `keyboard dismiss` over navigation. On iOS, keep an app session open first; `keyboard status|get` remains Android-only.
|
|
59
|
-
- When a task asks to "go back", use plain `back` for predictable app-owned navigation and reserve `back --system` for platform back gestures or button semantics.
|
|
60
|
-
- Use `type --delay-ms` or `fill --delay-ms` for debounced search fields that drop characters when typed too quickly.
|
|
61
|
-
- If there is no simulator, no app install, or no open app session yet, switch to `bootstrap-install.md` instead of improvising setup steps.
|
|
62
|
-
- Use the smallest unblock action first when transient UI blocks inspection, but do not navigate, search, or enter new text just to make the UI reveal data unless the user asked for that interaction.
|
|
63
|
-
- In React Native dev or debug apps, treat visible warning or error overlays as transient blockers unless the user is explicitly asking you to diagnose them. Dismiss them when safe, then continue the requested flow.
|
|
64
|
-
- For React Native code changes where the app is already connected to Metro, prefer `agent-device metro reload`, then wait and re-snapshot. Use `open <app> --relaunch` only when Metro reload does not reconnect or native startup state must reset.
|
|
65
|
-
- Do not use external lookups to compensate for missing on-screen data unless the user asked for them.
|
|
66
|
-
- If the needed information is not exposed on screen, say that plainly instead of compensating with extra navigation, text entry, or web search.
|
|
67
|
-
- Prefer `@ref` or selector targeting over raw coordinates.
|
|
68
|
-
|
|
69
|
-
## Additional references
|
|
70
|
-
|
|
71
|
-
- Need logs, network, alerts, permissions, or failure triage: [references/debugging.md](references/debugging.md)
|
|
72
|
-
- Need screenshots, diff, recording, replay maintenance, or perf data: [references/verification.md](references/verification.md)
|
|
73
|
-
- Need desktop surfaces, menu bar behavior, or macOS-specific interaction rules: [references/macos-desktop.md](references/macos-desktop.md)
|
|
74
|
-
- Need remote HTTP transport, `connect --remote-config`, or tenant leases on a remote macOS host: [references/remote-tenancy.md](references/remote-tenancy.md)
|
|
75
|
-
This includes remote React Native runs where `agent-device` now prepares Metro locally and manages the local Metro companion tunnel automatically.
|
|
76
|
-
- Need the React Native component tree, props, state, hooks, or render profiling: use `agent-device react-devtools ...` and the [react-devtools skill](../react-devtools/SKILL.md).
|
|
34
|
+
Keep refs current, prefer selectors/refs over coordinates, use `fill` to replace text, and use `back` for app-owned navigation. Let `help workflow` provide the exact command shapes.
|
package/skills/dogfood/SKILL.md
CHANGED
|
@@ -1,184 +1,25 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dogfood
|
|
3
|
-
description:
|
|
3
|
+
description: Systematically explore and test a mobile app on iOS/Android with agent-device to find bugs, UX issues, and other problems. Use when asked to dogfood, QA, exploratory test, find issues, bug hunt, or test this app on mobile.
|
|
4
4
|
allowed-tools: Bash(agent-device:*), Bash(npx agent-device:*)
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Dogfood
|
|
7
|
+
# Dogfood
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Setup
|
|
12
|
-
|
|
13
|
-
Only the **Target app** is required. Everything else has sensible defaults.
|
|
14
|
-
|
|
15
|
-
| Parameter | Default | Example override |
|
|
16
|
-
| -------------------- | ----------------------------------------------------------- | -------------------------------------------- |
|
|
17
|
-
| **Target app** | _(required)_ | `Settings`, `com.example.app`, deep link URL |
|
|
18
|
-
| **Platform** | Infer from user context; otherwise ask (`ios` or `android`) | `--platform ios` |
|
|
19
|
-
| **Session name** | Slugified app/platform (for example `settings-ios`) | `--session my-session` |
|
|
20
|
-
| **Output directory** | `./dogfood-output/` | `Output directory: /tmp/mobile-qa` |
|
|
21
|
-
| **Scope** | Full app | `Focus on onboarding and profile` |
|
|
22
|
-
| **Authentication** | None | `Sign in to user@example.com` |
|
|
23
|
-
|
|
24
|
-
If the user gives enough context to start, begin immediately with defaults. Ask follow-up only when a required detail is missing (for example platform or credentials).
|
|
25
|
-
|
|
26
|
-
Prefer direct `agent-device` binary when available.
|
|
27
|
-
|
|
28
|
-
## Workflow
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
1. Initialize Set up session, output dirs, report file
|
|
32
|
-
2. Launch/Auth Open app and sign in if needed
|
|
33
|
-
3. Orient Capture initial snapshot and map navigation
|
|
34
|
-
4. Explore Systematically test flows and states
|
|
35
|
-
5. Document Record reproducible evidence per issue
|
|
36
|
-
6. Wrap up Reconcile summary, close session
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### 1. Initialize
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
mkdir -p {OUTPUT_DIR}/screenshots {OUTPUT_DIR}/videos
|
|
43
|
-
cp {SKILL_DIR}/templates/dogfood-report-template.md {OUTPUT_DIR}/report.md
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### 2. Launch/Auth
|
|
47
|
-
|
|
48
|
-
Start a named session and launch target app:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
agent-device --session {SESSION} open {TARGET_APP} --platform {PLATFORM}
|
|
52
|
-
agent-device --session {SESSION} snapshot -i
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
If login is required:
|
|
9
|
+
Router for exploratory QA. Private setup before using this skill:
|
|
56
10
|
|
|
57
11
|
```bash
|
|
58
|
-
agent-device --
|
|
59
|
-
agent-device --session {SESSION} fill @e1 "{EMAIL}"
|
|
60
|
-
agent-device --session {SESSION} fill @e2 "{PASSWORD}"
|
|
61
|
-
agent-device --session {SESSION} press @e3
|
|
62
|
-
agent-device --session {SESSION} wait 1000
|
|
63
|
-
agent-device --session {SESSION} snapshot -i
|
|
12
|
+
agent-device --version
|
|
64
13
|
```
|
|
65
14
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
### 3. Orient
|
|
15
|
+
Require `agent-device >= 0.13.4`; older CLIs lack these help topics. If older, run `npm install -g agent-device@latest`, recheck, then continue. If you cannot upgrade, stop and tell the user. Do not include version/upgrade commands in final plans.
|
|
69
16
|
|
|
70
|
-
|
|
17
|
+
Read current CLI guidance:
|
|
71
18
|
|
|
72
19
|
```bash
|
|
73
|
-
agent-device
|
|
74
|
-
agent-device --session {SESSION} snapshot -i
|
|
20
|
+
agent-device help dogfood
|
|
75
21
|
```
|
|
76
22
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
### 4. Explore
|
|
80
|
-
|
|
81
|
-
Read [references/issue-taxonomy.md](references/issue-taxonomy.md) for severity/category calibration.
|
|
82
|
-
|
|
83
|
-
Strategy:
|
|
84
|
-
|
|
85
|
-
- Move through each major app area (tabs, drawers, settings pages).
|
|
86
|
-
- Test core journeys end-to-end (create, edit, delete, submit, recover).
|
|
87
|
-
- Validate edge states (empty/error/loading/offline/permissions denied).
|
|
88
|
-
- Use `diff snapshot -i` after UI transitions to avoid stale refs.
|
|
89
|
-
- Periodically capture `logs path` and inspect the app log when behavior looks suspicious.
|
|
90
|
-
|
|
91
|
-
Useful commands per screen:
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
agent-device --session {SESSION} snapshot -i
|
|
95
|
-
agent-device --session {SESSION} screenshot {OUTPUT_DIR}/screenshots/{screen-name}.png
|
|
96
|
-
agent-device --session {SESSION} appstate
|
|
97
|
-
agent-device --session {SESSION} logs path
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### 5. Document Issues (Repro-First)
|
|
101
|
-
|
|
102
|
-
Explore and document in one pass. When you find an issue, stop and fully capture evidence before continuing.
|
|
103
|
-
|
|
104
|
-
#### Interactive/behavioral issues
|
|
105
|
-
|
|
106
|
-
Use video + step screenshots:
|
|
107
|
-
|
|
108
|
-
1. Start recording:
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
agent-device --session {SESSION} record start {OUTPUT_DIR}/videos/issue-{NNN}-repro.mp4
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
2. Reproduce with visible pacing. Capture each step:
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
agent-device --session {SESSION} screenshot {OUTPUT_DIR}/screenshots/issue-{NNN}-step-1.png
|
|
118
|
-
sleep 1
|
|
119
|
-
# perform action
|
|
120
|
-
sleep 1
|
|
121
|
-
agent-device --session {SESSION} screenshot {OUTPUT_DIR}/screenshots/issue-{NNN}-step-2.png
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
3. Capture final broken state:
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
sleep 2
|
|
128
|
-
agent-device --session {SESSION} screenshot {OUTPUT_DIR}/screenshots/issue-{NNN}-result.png
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
4. Stop recording:
|
|
132
|
-
|
|
133
|
-
```bash
|
|
134
|
-
agent-device --session {SESSION} record stop
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
5. Append issue immediately to report with numbered steps and screenshot references.
|
|
138
|
-
|
|
139
|
-
#### Static/on-load issues
|
|
140
|
-
|
|
141
|
-
Single screenshot is sufficient; no video required:
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
agent-device --session {SESSION} screenshot {OUTPUT_DIR}/screenshots/issue-{NNN}.png
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Set **Repro Video** to `N/A` in the report.
|
|
148
|
-
|
|
149
|
-
### 6. Wrap Up
|
|
150
|
-
|
|
151
|
-
Target 5-10 well-evidenced issues, then finish:
|
|
152
|
-
|
|
153
|
-
1. Reconcile summary severity counts in `report.md`.
|
|
154
|
-
2. Close session:
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
agent-device --session {SESSION} close
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
3. Report total issues, severity breakdown, and highest-risk findings.
|
|
161
|
-
|
|
162
|
-
## Guidance
|
|
163
|
-
|
|
164
|
-
- Repro quality matters more than issue count.
|
|
165
|
-
- Use refs (`@eN`) for fast exploration, selectors for deterministic replay assertions when needed.
|
|
166
|
-
- Re-snapshot after any mutation (navigation, modal, list update, form submit).
|
|
167
|
-
- Use `fill` for clear-then-type semantics; use `type` for incremental typing behavior checks.
|
|
168
|
-
- Keep logs optional and targeted: enable/read app logs only when useful for diagnosis.
|
|
169
|
-
- If the issue appears rooted in React Native internals rather than device/app runtime behavior, use `agent-device react-devtools ...` and the `skills/react-devtools` workflow for component-tree or render-profiling inspection.
|
|
170
|
-
- Never read source code of the app under test; findings must come from observed runtime behavior.
|
|
171
|
-
- Write each issue immediately to avoid losing evidence.
|
|
172
|
-
- Never delete screenshots/videos/report artifacts during a session.
|
|
173
|
-
|
|
174
|
-
## References
|
|
175
|
-
|
|
176
|
-
| Reference | When to Read |
|
|
177
|
-
| ------------------------------------------------------------ | ----------------------------------------------- |
|
|
178
|
-
| [references/issue-taxonomy.md](references/issue-taxonomy.md) | Start of session; severity/categories/checklist |
|
|
179
|
-
|
|
180
|
-
## Templates
|
|
23
|
+
Loop: open named session -> snapshot -i + screenshot -> explore flows -> capture evidence per issue -> close.
|
|
181
24
|
|
|
182
|
-
|
|
183
|
-
| ---------------------------------------------------------------------------- | --------------------------------------------- |
|
|
184
|
-
| [templates/dogfood-report-template.md](templates/dogfood-report-template.md) | Copy into output directory as the report file |
|
|
25
|
+
Target app is required; infer platform or ask. Default output is `./dogfood-output/`. Findings must come from runtime behavior, not source reads. Re-snapshot after mutations. Use logs, network, trace, perf, overlay screenshots, or react-devtools only when they add evidence.
|
|
@@ -1,55 +1,39 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: react-devtools
|
|
3
|
-
description: Inspect and profile React Native component trees from agent-device. Use
|
|
3
|
+
description: Inspect and profile React Native component trees from agent-device. Use for React Native performance, profiling, props, state, hooks, render causes, slow components, excessive rerenders, or questions like why a component rerendered.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# react-devtools
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Router for React Native internals. Private setup before using this skill:
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
```bash
|
|
11
|
+
agent-device --version
|
|
12
|
+
```
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
Require `agent-device >= 0.13.4`; older CLIs lack these help topics. If older, run `npm install -g agent-device@latest`, recheck, then continue. If you cannot upgrade, stop and tell the user. Do not include version/upgrade commands in final plans.
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Read current CLI guidance:
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
4. Inspect with `get tree`, `find`, and `get component`.
|
|
20
|
-
5. Profile only around the interaction being investigated.
|
|
21
|
-
6. Verify the fix with the same command sequence and interaction.
|
|
18
|
+
```bash
|
|
19
|
+
agent-device help react-devtools
|
|
20
|
+
```
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
Use `agent-device react-devtools ...` for component tree, props, state, hooks, render ownership, performance profiling, slow components, or rerenders. It dynamically runs pinned `agent-react-devtools@0.4.0`. Use normal `agent-device` commands for visible UI, refs, screenshots, logs, network, or device-level perf.
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
Core loop:
|
|
26
25
|
|
|
27
26
|
```bash
|
|
28
27
|
agent-device react-devtools status
|
|
29
28
|
agent-device react-devtools wait --connected
|
|
30
29
|
agent-device react-devtools get tree --depth 3
|
|
31
|
-
agent-device react-devtools find <ComponentName>
|
|
32
|
-
agent-device react-devtools get component @c5
|
|
33
30
|
agent-device react-devtools profile start
|
|
31
|
+
# perform the interaction with normal agent-device commands
|
|
34
32
|
agent-device react-devtools profile stop
|
|
35
33
|
agent-device react-devtools profile slow --limit 5
|
|
36
34
|
agent-device react-devtools profile rerenders --limit 5
|
|
37
35
|
```
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
- Need current UI text, refs, screenshots, logs, network, or device metrics: use the `agent-device` skill.
|
|
42
|
-
- Need props, state, hooks, component ownership, render causes, or React profiler data: use this skill.
|
|
43
|
-
- Start component-tree reads with `get tree --depth 3` or `find <name>` to keep output bounded.
|
|
44
|
-
- Labels like `@c5` reset when the app reloads or components remount. After reload, run `wait --connected` and inspect again.
|
|
45
|
-
- Profiling only captures renders between `profile start` and `profile stop`.
|
|
46
|
-
- On Android, set `adb reverse tcp:8097 tcp:8097` for React DevTools. If Metro is local, also set `adb reverse tcp:8081 tcp:8081`.
|
|
47
|
-
- For Android sessions connected through `agent-device connect --remote-config`, run `agent-device react-devtools ...` normally. The CLI registers a bridge companion tunnel to the local DevTools daemon on `127.0.0.1:8097` and unregisters it when the command exits.
|
|
48
|
-
- Remote Android React DevTools assumes the React Native-bundled DevTools behavior in React Native 0.83+. Do not assume older browser/Chromium DevTools workflows exist in remote sandboxes. For Expo apps, verify the SDK's bundled React Native version and runtime behavior first; no Expo SDK version is separately verified by this skill.
|
|
49
|
-
|
|
50
|
-
## References
|
|
37
|
+
Rules:
|
|
51
38
|
|
|
52
|
-
|
|
53
|
-
| --------------------------------------- | --------------------------------------------- |
|
|
54
|
-
| [commands.md](references/commands.md) | Command reference and common inspection flows |
|
|
55
|
-
| [profiling.md](references/profiling.md) | Render profiling workflow and interpretation |
|
|
39
|
+
Keep reads bounded with `--depth`/`find`, treat `@c` refs as reload-local, profile only the investigated interaction, and run the same command in remote Android sessions; the CLI manages the needed local service tunnel.
|
package/dist/src/4993.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let e=["android.shell","ios.runnerCommand","macos.desktopScreenshot"],n={"android.shell":"androidShell","ios.runnerCommand":"iosRunnerCommand","macos.desktopScreenshot":"macosDesktopScreenshot"};function o(e,n){return e.capabilities?.includes(n)??!1}function a(e,o){let a=n[o];return"function"==typeof e.escapeHatches?.[a]}export{n as BACKEND_CAPABILITY_ESCAPE_HATCH_METHODS,e as BACKEND_CAPABILITY_NAMES,o as hasBackendCapability,a as hasBackendEscapeHatch};
|
package/dist/src/5721.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import e from"node:fs";let t=RegExp("\\b(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)\\b\\s+https?:\\/\\/","i"),r=/https?:\/\/[^\s"'<>\])]+/i,n=[/\bstatus(?:Code)?["'=: ]+([1-5]\d{2})\b/i,/\bresponse(?:\s+code)?["'=: ]+([1-5]\d{2})\b/i,/\bHTTP\/[0-9.]+\s+([1-5]\d{2})\b/i],i="<memory>";function s(e,t,r=e.limits.maxEntries){let n=[...e.entries],i=new Set(n.map(e=>o(e)));for(let e of t.entries){let t=o(e);if(!i.has(t)&&(i.add(t),n.push(e),n.length>=r))break}return{...e,matchedLines:n.length,entries:n}}function u(t,r){let n=y(r?.maxEntries,25,1,200),i=r?.include??"summary",s=y(r?.maxPayloadChars,2048,64,16384),u=y(r?.maxScanLines,4e3,100,2e4);return e.existsSync(t)?l(e.readFileSync(t,"utf8"),{...r,path:t}):{path:t,exists:!1,scannedLines:0,matchedLines:0,entries:[],include:i,limits:{maxEntries:n,maxPayloadChars:s,maxScanLines:u}}}function l(e,n){let s=y(n?.maxEntries,25,1,200),u=n?.backend,l=n?.include??"summary",o=y(n?.maxPayloadChars,2048,64,16384),g=y(n?.maxScanLines,4e3,100,2e4),N=e.split("\n"),T=Math.max(0,N.length-g),E=N.slice(T),I=[];for(let e=E.length-1;e>=0&&I.length<s;e-=1){let n=E[e];if(!n?.trim())continue;let i=function(e,n,i,s,u,l){let o=e[n]?.trim();if(!o)return null;let y=function(e){let t=e.indexOf("{");if(t<0)return null;let r=e.lastIndexOf("}");if(r<=t)return null;let n=e.slice(t,r+1);try{let e=JSON.parse(n);return e&&"object"==typeof e?e:null}catch{return null}}(o),g=p(y,["method","httpMethod"]),N=p(y,["url","requestUrl"]),T=function(e,t){if(!e)return null;for(let r of t){let t=e[r];if("number"==typeof t&&Number.isInteger(t))return t;if("string"==typeof t&&/^\d{3}$/.test(t.trim()))return Number.parseInt(t.trim(),10)}return null}(y,["status","statusCode","responseCode"]),E=t.exec(o),I=/\bmethod["'=: ]+([A-Z]+)\b/i.exec(o),M=(g??I?.[1]??E?.[1])?.toUpperCase(),$=r.exec(o),L=N??$?.[0];if(!L)return null;let O=T??d(o)??void 0;if(!(g||I?.[1]||E?.[1]||void 0!==O||/\bURL["'=: ]+https?:\/\//i.test(o)||/\bheaders?["'=: ]+/i.test(o)||/\b(?:requestBody|responseBody|payload|request|response)["'=: ]+/i.test(o)))return null;let S={method:M,url:L,status:O,timestamp:f(o),packetId:m(o)??void 0,durationMs:c(o)??void 0,raw:x(o,l),line:i};if("android"===s&&function(e,t,r){let n=a(t,r,5),i=e.packetId??n.map(e=>m(e)).find(e=>"string"==typeof e&&e.length>0);i&&(e.packetId=i);let s=i?a(t,r,12).filter(e=>m(e)===i):n;e.timestamp||(e.timestamp=s.map(e=>f(e)).find(e=>"string"==typeof e&&e.length>0)),void 0===e.status&&(e.status=s.map(e=>d(e)).find(e=>"number"==typeof e)),void 0===e.durationMs&&(e.durationMs=s.map(e=>c(e)).find(e=>"number"==typeof e))}(S,e,n),"headers"===u||"all"===u){let e=function(e,t){if(t){let e=t.headers??t.requestHeaders??t.responseHeaders;if(void 0!==e)return b(e)}let r=/\bheaders?["'=: ]+(\{.*\})/i.exec(e);return r?.[1]?.trim()}(o,y);e&&(S.headers=x(e,l))}if("body"===u||"all"===u){let e=h(o,y,["requestBody","body","payload","request"]),t=h(o,y,["responseBody","response"]);e&&(S.requestBody=x(e,l)),t&&(S.responseBody=x(t,l))}return S}(E,e,T+e+1,u,l,o);i&&I.push(i)}return{path:n?.path??i,exists:!0,scannedLines:E.length,matchedLines:I.length,entries:I,include:l,limits:{maxEntries:s,maxPayloadChars:o,maxScanLines:g}}}function o(e){return`${e.timestamp??""}|${e.method??""}|${e.url}|${e.status??""}|${e.raw}`}function a(e,t,r){let n=[],i=Math.max(0,t-r),s=Math.min(e.length-1,t+r);for(let t=i;t<=s;t+=1){let r=e[t]?.trim();r&&n.push(r)}return n}function d(e){for(let t of n){let r=t.exec(e);if(!r)continue;let n=Number.parseInt(r[1]??"",10);if(Number.isInteger(n))return n}return null}function f(e){let t=/\b\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?\b/.exec(e);if(t)return t[0];let r=/\b\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\b/.exec(e);return r?.[0]}function m(e){let t=/\bpacket id (\d+)\b/i.exec(e);return t?.[1]??null}function c(e){let t=/\b(?:duration|elapsed request\/response time, ms)[:= ]+(\d+)\b/i.exec(e);if(!t)return null;let r=Number.parseInt(t[1]??"",10);return Number.isInteger(r)?r:null}function p(e,t){if(e)for(let r of t){let t=e[r];if("string"==typeof t&&t.trim().length>0)return t.trim()}}function h(e,t,r){if(t){for(let e of r)if(void 0!==t[e])return b(t[e])}for(let t of r){let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=RegExp(`\\b${r}["'=: ]+(.+)$`,"i").exec(e);if(n?.[1])return n[1].trim()}}function b(e){if("string"==typeof e)return e;try{return JSON.stringify(e)}catch{return String(e)}}function x(e,t){return e.length<=t?e:`${e.slice(0,t)}...<truncated>`}function y(e,t,r,n){return void 0!==e&&Number.isInteger(e)?Math.max(r,Math.min(n,e)):t}export{i as NETWORK_LOG_MEMORY_PATH,s as mergeNetworkDumps,u as readRecentNetworkTraffic,l as readRecentNetworkTrafficFromText};
|
package/dist/src/7166.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let e=/(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)/i,r=/\b[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\.[A-Za-z0-9_-]{16,}\b/g;function t(e){var t,s;let o=!1,i=e;return{value:(t=i=(i=(i=(i=(i=i.replaceAll(/(authorization|token|secret|password|passwd|api[-_]?key)=([^&\s]+)/gi,(e,r)=>(o=!0,`${String(r)}=[REDACTED]`))).replaceAll(/("(?:authorization|cookie|token|secret|password|passwd|api[-_]?key)"\s*:\s*")([^"]*)(")/gi,(e,r,t,a)=>(o=!0,`${String(r)}[REDACTED]${String(a)}`))).replaceAll(/\b(Bearer\s+)([^\s",;]+)/gi,(e,r)=>(o=!0,`${String(r)}[REDACTED]`))).replaceAll(/((?:authorization|cookie|token|secret|password|passwd|api[-_]?key)\s*[:=]\s*)([^\s,;&]+)/gi,(e,r)=>(o=!0,`${String(r)}[REDACTED]`))).replaceAll(r,()=>(o=!0,"[REDACTED]")),s=()=>{o=!0},i=/(https?:\/\/|token|secret|password|authorization|cookie|api[-_]?key)/i.test(t)?t.replaceAll(/https?:\/\/[^\s"'<>)]+/gi,e=>{let r=a(e);return r?(r.redacted&&s(),r.value):e}):t),redacted:o}}function a(r){try{let t=new URL(r),a=function(r){let t=!1;for(let a of Array.from(r.searchParams.keys()))e.test(a)&&(r.searchParams.set(a,"[REDACTED]"),t=!0);return t}(t);return(t.username||t.password)&&(t.username="REDACTED",t.password="REDACTED",a=!0),{value:t.toString(),redacted:a}}catch{return}}export{t as redactNetworkLogText,a as redactNetworkUrl};
|
package/dist/src/8564.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import e from"node:fs";import t from"node:path";import{fileURLToPath as n}from"node:url";import{AsyncLocalStorage as a}from"node:async_hooks";import i from"node:crypto";import r from"node:os";import{redactDiagnosticData as o,AppError as s}from"./9152.js";import{withSuccessText as l,bindCommands as d,successText as u}from"./9076.js";import{hasBackendEscapeHatch as c,hasBackendCapability as p}from"./4993.js";import{resolveUserPath as m,expandUserHomePath as f}from"./3267.js";function g(e){let t={backend:e.backend,artifacts:e.artifacts,sessions:e.sessions??h(),policy:e.policy??v(),diagnostics:e.diagnostics,clock:e.clock,signal:e.signal};return{...t,...d(t)}}function h(e=[]){let t=new Map(e.map(e=>[e.name,I(e)]));return{get:e=>I(t.get(e)),set:e=>{t.set(e.name,I(e))},delete:e=>{t.delete(e)},list:()=>Array.from(t.values(),e=>I(e))}}function I(e){if(e)return{...e,...e.snapshot?{snapshot:structuredClone(e.snapshot)}:{},...e.metadata?{metadata:function(e){try{return structuredClone(e)}catch{return{...e}}}(e.metadata)}:{}}}function S(e={}){return{allowLocalInputPaths:!0,allowLocalOutputPaths:!0,maxImagePixels:2e7,allowNamedBackendCapabilities:[],...e}}function v(e={}){return{allowLocalInputPaths:!1,allowLocalOutputPaths:!1,maxImagePixels:2e7,allowNamedBackendCapabilities:[],...e}}function w(e,t){if(!p(e.backend,t))throw new s("UNSUPPORTED_OPERATION",`Backend capability ${t} is not supported by this backend`,{capability:t});if(!e.policy.allowNamedBackendCapabilities.includes(t))throw new s("UNSUPPORTED_OPERATION",`Backend capability ${t} is not allowed by command policy`,{capability:t});if(!c(e.backend,t))throw new s("UNSUPPORTED_OPERATION",`Backend capability ${t} does not implement its escape hatch method`,{capability:t})}function b(){try{let n=y();return JSON.parse(e.readFileSync(t.join(n,"package.json"),"utf8")).version??"0.0.0"}catch{return"0.0.0"}}function y(){let a=t.dirname(n(import.meta.url)),i=a;for(let n=0;n<6;n+=1){let n=t.join(i,"package.json");if(e.existsSync(n))return i;i=t.dirname(i)}return a}let P=new a;function k(){return i.randomBytes(8).toString("hex")}async function _(e,t){let n={...e,diagnosticId:`${Date.now().toString(36)}-${i.randomBytes(4).toString("hex")}`,events:[]};return await P.run(n,t)}function N(){let e=P.getStore();return e?{diagnosticId:e.diagnosticId,requestId:e.requestId,session:e.session,command:e.command,debug:e.debug}:{}}function D(t){let n=P.getStore();if(!n)return;let a={ts:new Date().toISOString(),level:t.level??"info",phase:t.phase,session:n.session,requestId:n.requestId,command:n.command,durationMs:t.durationMs,data:t.data?o(t.data):void 0};if(n.events.push(a),!n.debug)return;let i=`[agent-device][diag] ${JSON.stringify(a)}
|
|
2
|
-
`;try{n.logPath&&e.appendFile(n.logPath,i,()=>{}),n.traceLogPath&&e.appendFile(n.traceLogPath,i,()=>{}),n.logPath||n.traceLogPath||process.stderr.write(i)}catch{}}async function $(e,t,n){let a=Date.now();try{let i=await t();return D({level:"info",phase:e,durationMs:Date.now()-a,data:n}),i}catch(t){throw D({level:"error",phase:e,durationMs:Date.now()-a,data:{...n??{},error:t instanceof Error?t.message:String(t)}}),t}}function C(n={}){let a=P.getStore();if(!a||!n.force&&!a.debug||0===a.events.length)return null;try{let n=(a.session??"default").replace(/[^a-zA-Z0-9._-]/g,"_"),i=new Date().toISOString().slice(0,10),s=t.join(r.homedir(),".agent-device","logs",n,i);e.mkdirSync(s,{recursive:!0});let l=new Date().toISOString().replace(/[:.]/g,"-"),d=t.join(s,`${l}-${a.diagnosticId}.ndjson`),u=a.events.map(e=>JSON.stringify(o(e)));return e.writeFileSync(d,`${u.join("\n")}
|
|
3
|
-
`),a.events=[],d}catch{return null}}function j(e){let n,a=(n=(e??"").trim())?m(n):t.join(f("~"),".agent-device");return{baseDir:a,infoPath:t.join(a,"daemon.json"),lockPath:t.join(a,"daemon.lock"),logPath:t.join(a,"daemon.log"),sessionsDir:t.join(a,"sessions")}}function R(e){let t=(e??"").trim().toLowerCase();return"http"===t?"http":"dual"===t?"dual":"socket"}function A(e){let t=(e??"").trim().toLowerCase();return"auto"===t?"auto":"socket"===t?"socket":"http"===t?"http":"auto"}function O(e){return"tenant"===(e??"").trim().toLowerCase()?"tenant":"none"}function x(e){if(!e)return;let t=e.trim();if(t&&/^[a-zA-Z0-9._-]{1,128}$/.test(t))return t}let z=/(?:^|[^\w$.])(?:import|export)\s+(?:type\s+)?(?:[^'"`]*?\s+from\s+)?['"]([^'"]+)['"]/gm,B=/import\(\s*['"]([^'"]+)['"]\s*\)/gm,E=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];function M(){let e=process.argv[1];return e?T(e):"unknown"}function T(n,a=y()){try{let r=t.resolve(a),o=[t.resolve(n)],s=new Set,l=[];for(;o.length>0;){let n=o.pop();if(!n||s.has(n))continue;s.add(n);let a=e.statSync(n);if(!a.isFile())continue;let i=t.relative(r,n)||n;l.push(`${i}:${a.size}:${Math.trunc(a.mtimeMs)}`);let d=e.readFileSync(n,"utf8");for(let e of function(e){let t=new Set;return L(e,z,t),L(e,B,t),[...t]}(d)){let a=function(e,n){let a=t.resolve(t.dirname(e),n),i=F(a);if(i)return i;for(let e of E){let t=F(`${a}${e}`);if(t)return t}for(let e of E){let n=F(t.join(a,`index${e}`));if(n)return n}return null}(n,e);a&&o.push(a)}}let d=l.sort().join("|"),u=i.createHash("sha1").update(d).digest("hex");return`graph:${l.length}:${u}`}catch{return"unknown"}}function L(e,t,n){t.lastIndex=0;let a=null;for(;null!==(a=t.exec(e));){let e=a[1]?.trim();e?.startsWith(".")&&n.add(e)}}function F(t){try{return e.statSync(t).isFile()?t:null}catch{return null}}function U(e){let t=e.appId??e.bundleId??e.packageName;return{session:e.session,appId:t,appBundleId:e.bundleId,package:e.packageName}}function K(e,t,n){return{deviceId:t,deviceName:n,..."android"===e?{serial:t}:"ios"===e?{udid:t}:{}}}function q(e,t={}){let n=t.includeAndroidSerial??!0;return{platform:e.platform,target:e.target,device:e.name,id:e.id,..."ios"===e.platform?{device_udid:e.ios?.udid??e.id,ios_simulator_device_set:e.ios?.simulatorSetPath??null}:{},..."android"===e.platform&&n?{serial:e.android?.serial??e.id}:{}}}function H(e){return{name:e.name,...q(e.device,{includeAndroidSerial:!1}),createdAt:e.createdAt}}function J(e){return{platform:e.platform,id:e.id,name:e.name,kind:e.kind,target:e.target,..."boolean"==typeof e.booted?{booted:e.booted}:{}}}function Z(e){let t=e.created?"Created":"Reused",n=e.booted?" (booted)":"";return l({udid:e.udid,device:e.device,runtime:e.runtime,ios_simulator_device_set:e.iosSimulatorDeviceSet??null,created:e.created,booted:e.booted},`${t}: ${e.device} ${e.udid}${n}`)}function V(e){return e.bundleId??e.package??e.app}function W(e){return l({app:e.app,appPath:e.appPath,platform:e.platform,...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.package?{package:e.package}:{}},`Installed: ${V(e)}`)}function G(e){return e.appName??e.bundleId??e.packageName??e.launchTarget}function Q(e){return l({launchTarget:e.launchTarget,...e.appName?{appName:e.appName}:{},...e.appId?{appId:e.appId}:{},...e.bundleId?{bundleId:e.bundleId}:{},...e.packageName?{package:e.packageName}:{},...e.installablePath?{installablePath:e.installablePath}:{},...e.archivePath?{archivePath:e.archivePath}:{},...e.materializationId?{materializationId:e.materializationId}:{},...e.materializationExpiresAt?{materializationExpiresAt:e.materializationExpiresAt}:{}},`Installed: ${G(e)}`)}function X(e){let t=e.appName??e.appBundleId??e.session;return l({session:e.session,...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.startup?{startup:e.startup}:{},...e.runtime?{runtime:e.runtime}:{},...e.device?q(e.device):{}},t?`Opened: ${t}`:"Opened")}function Y(e){return{session:e.session,...e.shutdown?{shutdown:e.shutdown}:{},...u(e.session?`Closed: ${e.session}`:"Closed")}}function ee(e){return{nodes:e.nodes,truncated:e.truncated,...e.appName?{appName:e.appName}:{},...e.appBundleId?{appBundleId:e.appBundleId}:{},...e.visibility?{visibility:e.visibility}:{},...e.warnings&&e.warnings.length>0?{warnings:e.warnings}:{}}}export{w as assertBackendCapabilityAllowed,U as buildAppIdentifiers,K as buildDeviceIdentifiers,T as computeDaemonCodeSignature,g as createAgentDevice,h as createMemorySessionStore,k as createRequestId,D as emitDiagnostic,y as findProjectRoot,C as flushDiagnosticsToSessionFile,N as getDiagnosticsMeta,S as localCommandPolicy,x as normalizeTenantId,b as readVersion,M as resolveDaemonCodeSignature,j as resolveDaemonPaths,R as resolveDaemonServerMode,A as resolveDaemonTransportPreference,V as resolveDeployResultTarget,G as resolveInstallFromSourceResultTarget,O as resolveSessionIsolationMode,v as restrictedCommandPolicy,Y as serializeCloseResult,W as serializeDeployResult,J as serializeDevice,Z as serializeEnsureSimulatorResult,Q as serializeInstallFromSourceResult,X as serializeOpenResult,H as serializeSessionListEntry,ee as serializeSnapshotResult,$ as withDiagnosticTimer,_ as withDiagnosticsScope};
|