swipium 1.0.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/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/appMap/automationLink.js +74 -0
- package/dist/appMap/automationLink.js.map +1 -0
- package/dist/appMap/build.js +193 -0
- package/dist/appMap/build.js.map +1 -0
- package/dist/appMap/codeIndex.js +73 -0
- package/dist/appMap/codeIndex.js.map +1 -0
- package/dist/appMap/featureModel.js +83 -0
- package/dist/appMap/featureModel.js.map +1 -0
- package/dist/appMap/firstRunApply.js +131 -0
- package/dist/appMap/firstRunApply.js.map +1 -0
- package/dist/appMap/fsWalk.js +75 -0
- package/dist/appMap/fsWalk.js.map +1 -0
- package/dist/appMap/issues.js +227 -0
- package/dist/appMap/issues.js.map +1 -0
- package/dist/appMap/migrations.js +87 -0
- package/dist/appMap/migrations.js.map +1 -0
- package/dist/appMap/prelaunch.js +66 -0
- package/dist/appMap/prelaunch.js.map +1 -0
- package/dist/appMap/projectRegistry.js +70 -0
- package/dist/appMap/projectRegistry.js.map +1 -0
- package/dist/appMap/provenance.js +52 -0
- package/dist/appMap/provenance.js.map +1 -0
- package/dist/appMap/query.js +118 -0
- package/dist/appMap/query.js.map +1 -0
- package/dist/appMap/runtimeMerge.js +207 -0
- package/dist/appMap/runtimeMerge.js.map +1 -0
- package/dist/appMap/schema.js +65 -0
- package/dist/appMap/schema.js.map +1 -0
- package/dist/appMap/screenMatch.js +75 -0
- package/dist/appMap/screenMatch.js.map +1 -0
- package/dist/appMap/staticScan.js +614 -0
- package/dist/appMap/staticScan.js.map +1 -0
- package/dist/appMap/store.js +173 -0
- package/dist/appMap/store.js.map +1 -0
- package/dist/appMap/tsAstScan.js +184 -0
- package/dist/appMap/tsAstScan.js.map +1 -0
- package/dist/artifacts/bundletool.js +199 -0
- package/dist/artifacts/bundletool.js.map +1 -0
- package/dist/artifacts/resolve.js +388 -0
- package/dist/artifacts/resolve.js.map +1 -0
- package/dist/automationGen/appiumModel.js +129 -0
- package/dist/automationGen/appiumModel.js.map +1 -0
- package/dist/automationGen/ciEmitter.js +80 -0
- package/dist/automationGen/ciEmitter.js.map +1 -0
- package/dist/automationGen/jsEmitter.js +440 -0
- package/dist/automationGen/jsEmitter.js.map +1 -0
- package/dist/automationGen/packagePatch.js +56 -0
- package/dist/automationGen/packagePatch.js.map +1 -0
- package/dist/automationGen/projectProfile.js +317 -0
- package/dist/automationGen/projectProfile.js.map +1 -0
- package/dist/automationGen/pythonEmitter.js +386 -0
- package/dist/automationGen/pythonEmitter.js.map +1 -0
- package/dist/automationGen/readmeEmitter.js +66 -0
- package/dist/automationGen/readmeEmitter.js.map +1 -0
- package/dist/automationGen/suitePlan.js +94 -0
- package/dist/automationGen/suitePlan.js.map +1 -0
- package/dist/automationGen/validation.js +150 -0
- package/dist/automationGen/validation.js.map +1 -0
- package/dist/build/parseBuildLog.js +119 -0
- package/dist/build/parseBuildLog.js.map +1 -0
- package/dist/build/plan.js +150 -0
- package/dist/build/plan.js.map +1 -0
- package/dist/ci/preflight.js +85 -0
- package/dist/ci/preflight.js.map +1 -0
- package/dist/cli/init.js +105 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scan.js +85 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/suite.js +85 -0
- package/dist/cli/suite.js.map +1 -0
- package/dist/cli/verify.js +62 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/consent/consent.js +43 -0
- package/dist/consent/consent.js.map +1 -0
- package/dist/context/detect.js +156 -0
- package/dist/context/detect.js.map +1 -0
- package/dist/context/findApps.js +198 -0
- package/dist/context/findApps.js.map +1 -0
- package/dist/context/projectRoot.js +41 -0
- package/dist/context/projectRoot.js.map +1 -0
- package/dist/context/scan.js +167 -0
- package/dist/context/scan.js.map +1 -0
- package/dist/core/target.js +115 -0
- package/dist/core/target.js.map +1 -0
- package/dist/core/targetPlan.js +140 -0
- package/dist/core/targetPlan.js.map +1 -0
- package/dist/drivers/DirectDriver.js +228 -0
- package/dist/drivers/DirectDriver.js.map +1 -0
- package/dist/drivers/Driver.js +4 -0
- package/dist/drivers/Driver.js.map +1 -0
- package/dist/drivers/SimctlDriver.js +127 -0
- package/dist/drivers/SimctlDriver.js.map +1 -0
- package/dist/drivers/WdaDriver.js +250 -0
- package/dist/drivers/WdaDriver.js.map +1 -0
- package/dist/explore/candidates.js +93 -0
- package/dist/explore/candidates.js.map +1 -0
- package/dist/explore/graph.js +116 -0
- package/dist/explore/graph.js.map +1 -0
- package/dist/explore/memory.js +35 -0
- package/dist/explore/memory.js.map +1 -0
- package/dist/explore/planner.js +105 -0
- package/dist/explore/planner.js.map +1 -0
- package/dist/explore/policy.js +85 -0
- package/dist/explore/policy.js.map +1 -0
- package/dist/explore/runner.js +475 -0
- package/dist/explore/runner.js.map +1 -0
- package/dist/explore/signatures.js +35 -0
- package/dist/explore/signatures.js.map +1 -0
- package/dist/explore/suite.js +55 -0
- package/dist/explore/suite.js.map +1 -0
- package/dist/featureTesting/executionBootstrap.js +140 -0
- package/dist/featureTesting/executionBootstrap.js.map +1 -0
- package/dist/firstRun/authStateMachine.js +83 -0
- package/dist/firstRun/authStateMachine.js.map +1 -0
- package/dist/firstRun/classifyScreen.js +201 -0
- package/dist/firstRun/classifyScreen.js.map +1 -0
- package/dist/firstRun/firstRunPlanner.js +207 -0
- package/dist/firstRun/firstRunPlanner.js.map +1 -0
- package/dist/firstRun/firstRunRunner.js +331 -0
- package/dist/firstRun/firstRunRunner.js.map +1 -0
- package/dist/firstRun/generatedDataPolicy.js +215 -0
- package/dist/firstRun/generatedDataPolicy.js.map +1 -0
- package/dist/firstRun/inputPlanner.js +67 -0
- package/dist/firstRun/inputPlanner.js.map +1 -0
- package/dist/firstRun/onboardingStateMachine.js +46 -0
- package/dist/firstRun/onboardingStateMachine.js.map +1 -0
- package/dist/firstRun/paywallPolicy.js +54 -0
- package/dist/firstRun/paywallPolicy.js.map +1 -0
- package/dist/firstRun/types.js +7 -0
- package/dist/firstRun/types.js.map +1 -0
- package/dist/fixtures/catalog.js +131 -0
- package/dist/fixtures/catalog.js.map +1 -0
- package/dist/flows/discover.js +18 -0
- package/dist/flows/discover.js.map +1 -0
- package/dist/flows/generate.js +211 -0
- package/dist/flows/generate.js.map +1 -0
- package/dist/flows/lint.js +97 -0
- package/dist/flows/lint.js.map +1 -0
- package/dist/flows/pack.js +68 -0
- package/dist/flows/pack.js.map +1 -0
- package/dist/flows/run.js +738 -0
- package/dist/flows/run.js.map +1 -0
- package/dist/flows/schema.js +240 -0
- package/dist/flows/schema.js.map +1 -0
- package/dist/flows/seedExec.js +108 -0
- package/dist/flows/seedExec.js.map +1 -0
- package/dist/flows/templates.js +155 -0
- package/dist/flows/templates.js.map +1 -0
- package/dist/flows/waitGuards.js +12 -0
- package/dist/flows/waitGuards.js.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/ios/signing.js +182 -0
- package/dist/ios/signing.js.map +1 -0
- package/dist/issues/classify.js +186 -0
- package/dist/issues/classify.js.map +1 -0
- package/dist/issues/fingerprint.js +130 -0
- package/dist/issues/fingerprint.js.map +1 -0
- package/dist/issues/index.js +240 -0
- package/dist/issues/index.js.map +1 -0
- package/dist/issues/metrics.js +155 -0
- package/dist/issues/metrics.js.map +1 -0
- package/dist/issues/recurrence.js +193 -0
- package/dist/issues/recurrence.js.map +1 -0
- package/dist/issues/report.js +110 -0
- package/dist/issues/report.js.map +1 -0
- package/dist/issues/reportBridge.js +119 -0
- package/dist/issues/reportBridge.js.map +1 -0
- package/dist/issues/schema.js +90 -0
- package/dist/issues/schema.js.map +1 -0
- package/dist/issues/sourceRevision.js +108 -0
- package/dist/issues/sourceRevision.js.map +1 -0
- package/dist/issues/store.js +155 -0
- package/dist/issues/store.js.map +1 -0
- package/dist/lib/android.js +278 -0
- package/dist/lib/android.js.map +1 -0
- package/dist/lib/commandTemplate.js +55 -0
- package/dist/lib/commandTemplate.js.map +1 -0
- package/dist/lib/coordSpace.js +23 -0
- package/dist/lib/coordSpace.js.map +1 -0
- package/dist/lib/device.js +87 -0
- package/dist/lib/device.js.map +1 -0
- package/dist/lib/gitignore.js +22 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/image.js +97 -0
- package/dist/lib/image.js.map +1 -0
- package/dist/lib/logger.js +8 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/metroState.js +45 -0
- package/dist/lib/metroState.js.map +1 -0
- package/dist/lib/needsInput.js +201 -0
- package/dist/lib/needsInput.js.map +1 -0
- package/dist/lib/png.js +103 -0
- package/dist/lib/png.js.map +1 -0
- package/dist/lib/redact.js +21 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/result.js +87 -0
- package/dist/lib/result.js.map +1 -0
- package/dist/lib/schemaHash.js +65 -0
- package/dist/lib/schemaHash.js.map +1 -0
- package/dist/lib/sensitive.js +13 -0
- package/dist/lib/sensitive.js.map +1 -0
- package/dist/lib/simctl.js +149 -0
- package/dist/lib/simctl.js.map +1 -0
- package/dist/lib/spawn.js +144 -0
- package/dist/lib/spawn.js.map +1 -0
- package/dist/lib/wda.js +347 -0
- package/dist/lib/wda.js.map +1 -0
- package/dist/lib/wdaConfig.js +69 -0
- package/dist/lib/wdaConfig.js.map +1 -0
- package/dist/lib/wdaTune.js +58 -0
- package/dist/lib/wdaTune.js.map +1 -0
- package/dist/oracle/auth.js +22 -0
- package/dist/oracle/auth.js.map +1 -0
- package/dist/oracle/failures.js +193 -0
- package/dist/oracle/failures.js.map +1 -0
- package/dist/oracle/health.js +123 -0
- package/dist/oracle/health.js.map +1 -0
- package/dist/oracle/record.js +36 -0
- package/dist/oracle/record.js.map +1 -0
- package/dist/orchestration/envelope.js +52 -0
- package/dist/orchestration/envelope.js.map +1 -0
- package/dist/orchestration/goal.js +98 -0
- package/dist/orchestration/goal.js.map +1 -0
- package/dist/plan/plan.js +124 -0
- package/dist/plan/plan.js.map +1 -0
- package/dist/prompts/index.js +63 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/report/artifactManifest.js +44 -0
- package/dist/report/artifactManifest.js.map +1 -0
- package/dist/report/coverage.js +60 -0
- package/dist/report/coverage.js.map +1 -0
- package/dist/report/evidence.js +84 -0
- package/dist/report/evidence.js.map +1 -0
- package/dist/report/export.js +447 -0
- package/dist/report/export.js.map +1 -0
- package/dist/report/flake.js +61 -0
- package/dist/report/flake.js.map +1 -0
- package/dist/report/history.js +564 -0
- package/dist/report/history.js.map +1 -0
- package/dist/report/policy.js +98 -0
- package/dist/report/policy.js.map +1 -0
- package/dist/report/qaLevel.js +96 -0
- package/dist/report/qaLevel.js.map +1 -0
- package/dist/report/readiness.js +213 -0
- package/dist/report/readiness.js.map +1 -0
- package/dist/report/summary.js +42 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/report/testCatalog.js +93 -0
- package/dist/report/testCatalog.js.map +1 -0
- package/dist/report/timing.js +37 -0
- package/dist/report/timing.js.map +1 -0
- package/dist/server.js +180 -0
- package/dist/server.js.map +1 -0
- package/dist/services/automationGenerate.js +60 -0
- package/dist/services/automationGenerate.js.map +1 -0
- package/dist/services/build.js +66 -0
- package/dist/services/build.js.map +1 -0
- package/dist/services/preflight.js +51 -0
- package/dist/services/preflight.js.map +1 -0
- package/dist/services/prepareAndroid.js +183 -0
- package/dist/services/prepareAndroid.js.map +1 -0
- package/dist/services/prepareIos.js +162 -0
- package/dist/services/prepareIos.js.map +1 -0
- package/dist/services/report.js +537 -0
- package/dist/services/report.js.map +1 -0
- package/dist/services/smoke.js +120 -0
- package/dist/services/smoke.js.map +1 -0
- package/dist/services/suiteGenerate.js +123 -0
- package/dist/services/suiteGenerate.js.map +1 -0
- package/dist/services/testSuiteKnowledge.js +150 -0
- package/dist/services/testSuiteKnowledge.js.map +1 -0
- package/dist/session/attach.js +47 -0
- package/dist/session/attach.js.map +1 -0
- package/dist/session/progress.js +56 -0
- package/dist/session/progress.js.map +1 -0
- package/dist/session/store.js +329 -0
- package/dist/session/store.js.map +1 -0
- package/dist/snapshot/overlays.js +132 -0
- package/dist/snapshot/overlays.js.map +1 -0
- package/dist/snapshot/parse.js +204 -0
- package/dist/snapshot/parse.js.map +1 -0
- package/dist/snapshot/present.js +12 -0
- package/dist/snapshot/present.js.map +1 -0
- package/dist/snapshot/settle.js +36 -0
- package/dist/snapshot/settle.js.map +1 -0
- package/dist/state/profile.js +318 -0
- package/dist/state/profile.js.map +1 -0
- package/dist/suite/compile.js +176 -0
- package/dist/suite/compile.js.map +1 -0
- package/dist/suite/lint.js +45 -0
- package/dist/suite/lint.js.map +1 -0
- package/dist/suite/pom.js +285 -0
- package/dist/suite/pom.js.map +1 -0
- package/dist/suite/testcase.js +87 -0
- package/dist/suite/testcase.js.map +1 -0
- package/dist/testSuite/generator.js +222 -0
- package/dist/testSuite/generator.js.map +1 -0
- package/dist/testSuite/history.js +44 -0
- package/dist/testSuite/history.js.map +1 -0
- package/dist/testSuite/issueLinks.js +96 -0
- package/dist/testSuite/issueLinks.js.map +1 -0
- package/dist/testSuite/merge.js +190 -0
- package/dist/testSuite/merge.js.map +1 -0
- package/dist/testSuite/schema.js +86 -0
- package/dist/testSuite/schema.js.map +1 -0
- package/dist/testSuite/store.js +116 -0
- package/dist/testSuite/store.js.map +1 -0
- package/dist/testSuite/traceability.js +55 -0
- package/dist/testSuite/traceability.js.map +1 -0
- package/dist/tools/act.js +457 -0
- package/dist/tools/act.js.map +1 -0
- package/dist/tools/agent.js +225 -0
- package/dist/tools/agent.js.map +1 -0
- package/dist/tools/appMap.js +317 -0
- package/dist/tools/appMap.js.map +1 -0
- package/dist/tools/assertVisual.js +74 -0
- package/dist/tools/assertVisual.js.map +1 -0
- package/dist/tools/automationGenerate.js +394 -0
- package/dist/tools/automationGenerate.js.map +1 -0
- package/dist/tools/capabilities.js +114 -0
- package/dist/tools/capabilities.js.map +1 -0
- package/dist/tools/clearOverlay.js +150 -0
- package/dist/tools/clearOverlay.js.map +1 -0
- package/dist/tools/detectContext.js +41 -0
- package/dist/tools/detectContext.js.map +1 -0
- package/dist/tools/doctor.js +116 -0
- package/dist/tools/doctor.js.map +1 -0
- package/dist/tools/explore.js +289 -0
- package/dist/tools/explore.js.map +1 -0
- package/dist/tools/firstRun.js +136 -0
- package/dist/tools/firstRun.js.map +1 -0
- package/dist/tools/flow.js +331 -0
- package/dist/tools/flow.js.map +1 -0
- package/dist/tools/flowGenerate.js +55 -0
- package/dist/tools/flowGenerate.js.map +1 -0
- package/dist/tools/getArtifact.js +39 -0
- package/dist/tools/getArtifact.js.map +1 -0
- package/dist/tools/health.js +41 -0
- package/dist/tools/health.js.map +1 -0
- package/dist/tools/ios.js +492 -0
- package/dist/tools/ios.js.map +1 -0
- package/dist/tools/jobs.js +20 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/network.js +50 -0
- package/dist/tools/network.js.map +1 -0
- package/dist/tools/note.js +69 -0
- package/dist/tools/note.js.map +1 -0
- package/dist/tools/plan.js +49 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/prepareIosTarget.js +99 -0
- package/dist/tools/prepareIosTarget.js.map +1 -0
- package/dist/tools/prepareTarget.js +257 -0
- package/dist/tools/prepareTarget.js.map +1 -0
- package/dist/tools/report.js +42 -0
- package/dist/tools/report.js.map +1 -0
- package/dist/tools/screenRecord.js +24 -0
- package/dist/tools/screenRecord.js.map +1 -0
- package/dist/tools/screenshot.js +63 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/smoke.js +39 -0
- package/dist/tools/smoke.js.map +1 -0
- package/dist/tools/snapshot.js +129 -0
- package/dist/tools/snapshot.js.map +1 -0
- package/dist/tools/startSession.js +169 -0
- package/dist/tools/startSession.js.map +1 -0
- package/dist/tools/state.js +87 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tools/suite.js +412 -0
- package/dist/tools/suite.js.map +1 -0
- package/dist/tools/testThis.js +774 -0
- package/dist/tools/testThis.js.map +1 -0
- package/dist/tools/wda.js +477 -0
- package/dist/tools/wda.js.map +1 -0
- package/dist/version.js +62 -0
- package/dist/version.js.map +1 -0
- package/dist/visual/ocr.js +72 -0
- package/dist/visual/ocr.js.map +1 -0
- package/dist/visual/provider.js +75 -0
- package/dist/visual/provider.js.map +1 -0
- package/docs/README.md +19 -0
- package/docs/assets/swipium-lockup-ink-on-light.png +0 -0
- package/docs/mcp-server.md +135 -0
- package/docs/tools.md +130 -0
- package/package.json +70 -0
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
// qa_ios (PHASE3-PLAN Phase 11) — iOS Simulator control via simctl. Boots/selects a simulator,
|
|
2
|
+
// installs a .app, launches/terminates, opens deep links, resets privacy, erases, and captures
|
|
3
|
+
// screenshots. Booting/launching binds a SimctlDriver into the session so the shared visual tools
|
|
4
|
+
// (qa_screenshot, qa_assert_visual, qa_report) work on iOS unchanged. Structured
|
|
5
|
+
// interaction (tap/type/snapshot) is intentionally unsupported here and reported as such.
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
8
|
+
import { isAbsolute, join } from 'node:path';
|
|
9
|
+
import { qaOk, qaError } from '../lib/result.js';
|
|
10
|
+
import { requireConsent, consumeConsent } from '../consent/consent.js';
|
|
11
|
+
import { sensitiveRefusal } from '../lib/sensitive.js';
|
|
12
|
+
import { captureCoordinateSpace } from '../lib/coordSpace.js';
|
|
13
|
+
import { SimctlDriver } from '../drivers/SimctlDriver.js';
|
|
14
|
+
import { WdaDriver } from '../drivers/WdaDriver.js';
|
|
15
|
+
import { checkWda, classifyWdaConnectionFailure, createWdaSession, wdaSessionUdidMismatch } from '../lib/wda.js';
|
|
16
|
+
import { loadWdaConfig, wdaUrlAllowedByConfig } from '../lib/wdaConfig.js';
|
|
17
|
+
import { recordWdaTiming } from '../lib/wdaTune.js';
|
|
18
|
+
import * as sim from '../lib/simctl.js';
|
|
19
|
+
/** Ensure a SimctlDriver is bound for `udid` and recorded on the session. */
|
|
20
|
+
function bind(sessions, session, udid) {
|
|
21
|
+
const driver = session.driver instanceof SimctlDriver ? session.driver : new SimctlDriver(udid);
|
|
22
|
+
driver.useDevice(udid);
|
|
23
|
+
session.driver = driver;
|
|
24
|
+
session.device = udid;
|
|
25
|
+
sessions.persist(session);
|
|
26
|
+
return driver;
|
|
27
|
+
}
|
|
28
|
+
function isLoopback(raw) {
|
|
29
|
+
try {
|
|
30
|
+
const u = new URL(raw);
|
|
31
|
+
return u.protocol === 'http:' && ['127.0.0.1', 'localhost', '::1'].includes(u.hostname);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function registerIos(server, sessions) {
|
|
38
|
+
server.registerTool('qa_ios', {
|
|
39
|
+
title: 'iOS simulator control',
|
|
40
|
+
description: 'Control an iOS Simulator (macOS only) and attach an external WDA backend. actions: list (available simulators), boot (boot/select one — binds it to the session), install (a .app, consent-gated), launch (a bundle id), terminate, openurl (deep link), screenshot, logs, privacy_reset (consent-gated), erase (consent-gated, wipes the device), wda_status, wda_attach. After boot/launch, qa_screenshot / qa_assert_visual / qa_report work on the simulator. For structured iOS tap/type/snapshot, attach WDA with action:"wda_attach".',
|
|
41
|
+
inputSchema: {
|
|
42
|
+
sessionId: z.string(),
|
|
43
|
+
action: z.enum(['list', 'boot', 'install', 'launch', 'terminate', 'openurl', 'screenshot', 'logs', 'privacy_reset', 'erase', 'wda_status', 'wda_attach']),
|
|
44
|
+
device: z.string().optional().describe('Simulator udid or name substring (for boot/erase), or expected WDA device UDID for wda_attach.'),
|
|
45
|
+
app: z.string().optional().describe('Path to a .app bundle (for install); absolute or relative to the project root.'),
|
|
46
|
+
bundleId: z.string().optional().describe('App bundle id (for launch/terminate/privacy_reset/wda_attach).'),
|
|
47
|
+
url: z.string().optional().describe('Deep link (for openurl).'),
|
|
48
|
+
webDriverAgentUrl: z.string().optional().describe('External WebDriverAgent base URL for wda_status/wda_attach. Defaults to http://127.0.0.1:8100.'),
|
|
49
|
+
allowNonLoopback: z.boolean().optional().describe('Required to use a non-loopback WDA URL.'),
|
|
50
|
+
last: z.string().optional().describe('Time range for logs, e.g. 5m, 30m, 1h. Defaults to 5m.'),
|
|
51
|
+
service: z.string().optional().describe('Privacy service for privacy_reset (e.g. location, photos, camera, all).'),
|
|
52
|
+
consentId: z.string().optional(),
|
|
53
|
+
approve: z.boolean().optional(),
|
|
54
|
+
},
|
|
55
|
+
}, async (args) => {
|
|
56
|
+
const { sessionId, action } = args;
|
|
57
|
+
const session = sessions.get(sessionId);
|
|
58
|
+
if (!session) {
|
|
59
|
+
return qaError({ what: `Unknown sessionId ${sessionId}`, changedState: false, retrySafe: true, nextSteps: ['Call qa_start_session first.'] });
|
|
60
|
+
}
|
|
61
|
+
if (action === 'wda_status' || action === 'wda_attach') {
|
|
62
|
+
const wdaConfig = loadWdaConfig(session.root);
|
|
63
|
+
const url = (args.webDriverAgentUrl ?? wdaConfig.url).replace(/\/+$/, '');
|
|
64
|
+
const loopback = isLoopback(url);
|
|
65
|
+
const configAllowed = !loopback && wdaUrlAllowedByConfig(wdaConfig, url);
|
|
66
|
+
if (!loopback && !args.allowNonLoopback && !configAllowed) {
|
|
67
|
+
return qaError({
|
|
68
|
+
what: 'Refused non-loopback WDA URL',
|
|
69
|
+
changedState: false,
|
|
70
|
+
retrySafe: false,
|
|
71
|
+
failureCode: 'DESTRUCTIVE_REFUSED',
|
|
72
|
+
nextSteps: ['Use a localhost WDA URL, pass allowNonLoopback with explicit consent, or add this exact URL to ios.wda.allowNonLoopbackUrls for a trusted isolated automation network.'],
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (!loopback && !configAllowed) {
|
|
76
|
+
const gate = consumeConsent(args.consentId, args.approve, { action: 'wda_non_loopback', affects: { url } });
|
|
77
|
+
if (!gate.approved) {
|
|
78
|
+
return requireConsent({
|
|
79
|
+
action: 'wda_non_loopback',
|
|
80
|
+
risk: 'medium',
|
|
81
|
+
affects: { url },
|
|
82
|
+
explain: `Use non-loopback WebDriverAgent URL ${url}? WDA is an automation server; only approve this on a trusted, isolated network.`,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const status = await checkWda(url);
|
|
87
|
+
const targetUdid = args.device ?? session.device;
|
|
88
|
+
const base = {
|
|
89
|
+
webDriverAgentUrl: url,
|
|
90
|
+
wda: status,
|
|
91
|
+
device: targetUdid ?? null,
|
|
92
|
+
sessionActive: session.driver instanceof WdaDriver,
|
|
93
|
+
driverKind: session.driver?.kind ?? null,
|
|
94
|
+
};
|
|
95
|
+
if (action === 'wda_status') {
|
|
96
|
+
return qaOk(base, `iOS WDA status: ${status.reachable ? 'reachable' : 'unreachable'} at ${url}${targetUdid ? ` device=${targetUdid}` : ''}`);
|
|
97
|
+
}
|
|
98
|
+
if (!targetUdid) {
|
|
99
|
+
return qaError({
|
|
100
|
+
what: 'Refused ambiguous WDA attach without a device UDID',
|
|
101
|
+
changedState: false,
|
|
102
|
+
retrySafe: true,
|
|
103
|
+
failureCode: 'MULTIPLE_DEVICES',
|
|
104
|
+
nextSteps: ['Pass device with the simulator/device UDID, or bind the session to a simulator first.'],
|
|
105
|
+
}, base);
|
|
106
|
+
}
|
|
107
|
+
if (session.device && session.device !== targetUdid) {
|
|
108
|
+
return qaError({
|
|
109
|
+
what: `Refused ambiguous WDA/device mapping: session is bound to ${session.device}, but qa_ios wda_attach was asked to use ${targetUdid}`,
|
|
110
|
+
changedState: false,
|
|
111
|
+
retrySafe: false,
|
|
112
|
+
failureCode: 'STALE_WDA_DEVICE',
|
|
113
|
+
nextSteps: ['Use the session-bound device, or start a new session for the other WDA/device pair.'],
|
|
114
|
+
}, base);
|
|
115
|
+
}
|
|
116
|
+
if (!status.reachable) {
|
|
117
|
+
return qaError({
|
|
118
|
+
what: `WDA server unavailable at ${url}`,
|
|
119
|
+
changedState: false,
|
|
120
|
+
retrySafe: true,
|
|
121
|
+
failureCode: classifyWdaConnectionFailure(status.error ?? 'unreachable'),
|
|
122
|
+
nextSteps: ['Start WebDriverAgent externally, confirm /status responds, then retry qa_ios wda_attach.'],
|
|
123
|
+
}, base);
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const bundleId = args.bundleId ?? session.appId ?? undefined;
|
|
127
|
+
const sessionOptions = { bundleId, udid: targetUdid, capabilities: wdaConfig.capabilities, settings: wdaConfig.settings };
|
|
128
|
+
const createStarted = Date.now();
|
|
129
|
+
let created;
|
|
130
|
+
try {
|
|
131
|
+
created = await createWdaSession(url, sessionOptions);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
recordWdaTiming(session, 'session_create', Date.now() - createStarted, sessions);
|
|
135
|
+
}
|
|
136
|
+
const mismatchedUdid = wdaSessionUdidMismatch(created.capabilities, targetUdid);
|
|
137
|
+
if (mismatchedUdid) {
|
|
138
|
+
sessions.recordMutation(session, {
|
|
139
|
+
tool: 'qa_ios',
|
|
140
|
+
action: 'wda_attach',
|
|
141
|
+
risk: 'medium',
|
|
142
|
+
target: { webDriverAgentUrl: url, device: targetUdid, bundleId: bundleId ?? null, reportedDevice: mismatchedUdid },
|
|
143
|
+
consent: { required: !loopback && !configAllowed, approved: !!configAllowed || loopback || !!args.approve },
|
|
144
|
+
status: 'blocked',
|
|
145
|
+
detail: 'WDA reported a different device',
|
|
146
|
+
});
|
|
147
|
+
return qaError({
|
|
148
|
+
what: `Refused stale WDA session: WDA reported device ${mismatchedUdid}, but qa_ios wda_attach requested ${targetUdid}`,
|
|
149
|
+
changedState: false,
|
|
150
|
+
retrySafe: false,
|
|
151
|
+
failureCode: 'STALE_WDA_DEVICE',
|
|
152
|
+
nextSteps: ['Stop the stale WDA process or start a new WDA session for the intended UDID.'],
|
|
153
|
+
}, { ...base, capabilities: created.capabilities ?? null, wdaSessionId: created.sessionId });
|
|
154
|
+
}
|
|
155
|
+
session.driver = new WdaDriver(url, { ...sessionOptions, sessionId: created.sessionId, onTiming: (kind, ms) => recordWdaTiming(session, kind, ms, sessions) });
|
|
156
|
+
session.device = targetUdid;
|
|
157
|
+
if (bundleId)
|
|
158
|
+
session.appId = bundleId;
|
|
159
|
+
sessions.persist(session);
|
|
160
|
+
sessions.addEnvChange(session, `ios wda attach ${url} ${targetUdid}`);
|
|
161
|
+
sessions.recordMutation(session, {
|
|
162
|
+
tool: 'qa_ios',
|
|
163
|
+
action: 'wda_attach',
|
|
164
|
+
risk: 'medium',
|
|
165
|
+
target: { webDriverAgentUrl: url, device: targetUdid, bundleId: bundleId ?? null, wdaSessionId: created.sessionId, capabilities: created.capabilities ?? null },
|
|
166
|
+
consent: { required: !loopback && !configAllowed, consentId: args.consentId, approved: true },
|
|
167
|
+
status: 'executed',
|
|
168
|
+
});
|
|
169
|
+
return qaOk({ ...base, sessionActive: true, wdaSessionId: created.sessionId, capabilities: created.capabilities ?? null }, `attached WDA structured iOS backend at ${url}\nNext: qa_snapshot / qa_act / qa_flow_run can use WDA-backed structured operations.`);
|
|
170
|
+
}
|
|
171
|
+
catch (e) {
|
|
172
|
+
const failureCode = classifyWdaConnectionFailure(String(e.message ?? e));
|
|
173
|
+
sessions.recordMutation(session, {
|
|
174
|
+
tool: 'qa_ios',
|
|
175
|
+
action: 'wda_attach',
|
|
176
|
+
risk: 'medium',
|
|
177
|
+
target: { webDriverAgentUrl: url, device: targetUdid, bundleId: args.bundleId ?? session.appId ?? null },
|
|
178
|
+
consent: { required: !loopback && !configAllowed, consentId: args.consentId, approved: !!configAllowed || loopback || !!args.approve },
|
|
179
|
+
status: 'blocked',
|
|
180
|
+
detail: String(e.message ?? e),
|
|
181
|
+
});
|
|
182
|
+
return qaError({
|
|
183
|
+
what: `WDA session creation failed: ${String(e.message ?? e)}`,
|
|
184
|
+
changedState: false,
|
|
185
|
+
retrySafe: true,
|
|
186
|
+
failureCode,
|
|
187
|
+
nextSteps: ['Confirm WDA is paired with the intended simulator/device and that the app bundle id is installed.'],
|
|
188
|
+
}, base);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (!(await sim.simctlAvailable())) {
|
|
192
|
+
return qaError({
|
|
193
|
+
what: 'iOS Simulator tooling is unavailable',
|
|
194
|
+
changedState: false,
|
|
195
|
+
retrySafe: false,
|
|
196
|
+
failureCode: 'BACKEND_UNSUPPORTED',
|
|
197
|
+
nextSteps: ['iOS support needs a macOS host with the `xcrun simctl` command-line tools. On Linux/Windows use the Android backend.'],
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
// ---- read-only ----
|
|
201
|
+
if (action === 'list') {
|
|
202
|
+
const sims = await sim.listSimulators();
|
|
203
|
+
const booted = sims.filter((s) => s.state === 'Booted');
|
|
204
|
+
return qaOk({ simulators: sims, bootedCount: booted.length }, `${sims.length} available simulators (${booted.length} booted):\n` + sims.slice(0, 25).map((s) => ` ${s.state === 'Booted' ? '▶' : '·'} ${s.name} [${s.runtime}] ${s.udid}`).join('\n'));
|
|
205
|
+
}
|
|
206
|
+
const need = (v, what) => v ? null : qaError({ what: `${action} requires ${what}`, changedState: false, retrySafe: true, nextSteps: [`Pass ${what}.`] });
|
|
207
|
+
if (action === 'boot') {
|
|
208
|
+
const sims = await sim.listSimulators();
|
|
209
|
+
const pick = (args.device && sims.find((s) => s.udid === args.device || s.name.toLowerCase().includes(args.device.toLowerCase()))) ||
|
|
210
|
+
sims.find((s) => s.state === 'Booted') ||
|
|
211
|
+
sims.find((s) => /iphone/i.test(s.name));
|
|
212
|
+
if (!pick)
|
|
213
|
+
return qaError({ what: 'No matching simulator', changedState: false, retrySafe: true, failureCode: 'SIMULATOR_RUNTIME_MISSING', nextSteps: ['qa_ios { action: "list" } to see available simulators, or install an iOS simulator runtime in Xcode.'] });
|
|
214
|
+
try {
|
|
215
|
+
sessions.milestone(session, 'simulator_boot_start');
|
|
216
|
+
await sim.boot(pick.udid);
|
|
217
|
+
sessions.milestone(session, 'simulator_boot_end');
|
|
218
|
+
}
|
|
219
|
+
catch (e) {
|
|
220
|
+
const msg = String(e);
|
|
221
|
+
const failureCode = /timed out|timeout/i.test(msg) ? 'SIMULATOR_BOOT_TIMEOUT' : 'SIMULATOR_BOOT_FAILED';
|
|
222
|
+
return qaError({ what: `Boot failed: ${msg}`, changedState: false, retrySafe: true, failureCode, nextSteps: ['Try another simulator from qa_ios list, erase the simulator if policy allows it, or boot a known-good simulator from Xcode.'] });
|
|
223
|
+
}
|
|
224
|
+
bind(sessions, session, pick.udid);
|
|
225
|
+
sessions.addEnvChange(session, `ios boot ${pick.name} (${pick.udid})`);
|
|
226
|
+
sessions.recordMutation(session, {
|
|
227
|
+
tool: 'qa_ios',
|
|
228
|
+
action: 'ios_boot',
|
|
229
|
+
risk: 'low',
|
|
230
|
+
target: { udid: pick.udid, name: pick.name, runtime: pick.runtime },
|
|
231
|
+
consent: { required: false, approved: true },
|
|
232
|
+
status: 'executed',
|
|
233
|
+
});
|
|
234
|
+
return qaOk({ udid: pick.udid, name: pick.name, runtime: pick.runtime, bound: true }, `booted + bound ${pick.name} [${pick.runtime}]\nNext: qa_ios install/launch, then qa_screenshot / qa_assert_visual.`);
|
|
235
|
+
}
|
|
236
|
+
// everything below needs a bound simulator
|
|
237
|
+
const udid = session.device;
|
|
238
|
+
if (!udid || !(session.driver instanceof SimctlDriver)) {
|
|
239
|
+
return qaError({ what: 'No simulator bound to this session', changedState: false, retrySafe: true, nextSteps: ['Call qa_ios { action: "boot" } first.'] });
|
|
240
|
+
}
|
|
241
|
+
if (action === 'install') {
|
|
242
|
+
const e = need(args.app, 'app (a .app path)');
|
|
243
|
+
if (e)
|
|
244
|
+
return e;
|
|
245
|
+
const appPath = isAbsolute(args.app) ? args.app : join(session.root, args.app);
|
|
246
|
+
if (!existsSync(appPath))
|
|
247
|
+
return qaError({ what: `.app not found: ${appPath}`, changedState: false, retrySafe: true, nextSteps: ['Provide an existing .app bundle path.'] });
|
|
248
|
+
const gate = consumeConsent(args.consentId, args.approve, { action: 'install_app', affects: { appPath } });
|
|
249
|
+
if (!gate.approved) {
|
|
250
|
+
sessions.recordMutation(session, {
|
|
251
|
+
tool: 'qa_ios',
|
|
252
|
+
action: 'install_app',
|
|
253
|
+
risk: 'medium',
|
|
254
|
+
target: { udid, appPath },
|
|
255
|
+
consent: { required: true, approved: false },
|
|
256
|
+
status: 'requested',
|
|
257
|
+
});
|
|
258
|
+
return requireConsent({ action: 'install_app', risk: 'medium', exactCommand: `xcrun simctl install ${udid} ${appPath}`, affects: { appPath }, explain: `Install ${appPath} onto the simulator? It runs third-party app code.` });
|
|
259
|
+
}
|
|
260
|
+
sessions.recordMutation(session, {
|
|
261
|
+
tool: 'qa_ios',
|
|
262
|
+
action: 'install_app',
|
|
263
|
+
risk: 'medium',
|
|
264
|
+
target: { udid, appPath },
|
|
265
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
266
|
+
status: 'approved',
|
|
267
|
+
});
|
|
268
|
+
try {
|
|
269
|
+
sessions.milestone(session, 'app_install_start');
|
|
270
|
+
await sim.installApp(udid, appPath);
|
|
271
|
+
sessions.milestone(session, 'app_install_end');
|
|
272
|
+
}
|
|
273
|
+
catch (err) {
|
|
274
|
+
const failureCode = sim.classifyIosInstallFailure(String(err));
|
|
275
|
+
sessions.recordMutation(session, {
|
|
276
|
+
tool: 'qa_ios',
|
|
277
|
+
action: 'install_app',
|
|
278
|
+
risk: 'medium',
|
|
279
|
+
target: { udid, appPath },
|
|
280
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
281
|
+
status: 'blocked',
|
|
282
|
+
detail: `${failureCode}: ${String(err)}`,
|
|
283
|
+
});
|
|
284
|
+
return qaError({ what: `Install failed: ${String(err)}`, changedState: false, retrySafe: true, failureCode, nextSteps: [failureCode === 'WRONG_ARCH' ? 'Rebuild the .app for the iOS Simulator SDK, not a physical device SDK.' : 'Confirm the .app is valid, signed as needed, and built for a simulator (not a device) SDK.'] });
|
|
285
|
+
}
|
|
286
|
+
const bundleId = await sim.bundleIdFromApp(appPath);
|
|
287
|
+
if (bundleId)
|
|
288
|
+
session.appId = bundleId;
|
|
289
|
+
sessions.addEnvChange(session, `ios install ${appPath}`);
|
|
290
|
+
sessions.recordMutation(session, {
|
|
291
|
+
tool: 'qa_ios',
|
|
292
|
+
action: 'install_app',
|
|
293
|
+
risk: 'medium',
|
|
294
|
+
target: { udid, appPath, bundleId: bundleId ?? null },
|
|
295
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
296
|
+
status: 'executed',
|
|
297
|
+
});
|
|
298
|
+
return qaOk({ installed: true, appPath, bundleId: bundleId ?? null }, `installed${bundleId ? ` (${bundleId})` : ''}. Next: qa_ios { action: "launch" }.`);
|
|
299
|
+
}
|
|
300
|
+
if (action === 'launch') {
|
|
301
|
+
const bundleId = args.bundleId ?? session.appId;
|
|
302
|
+
const e = need(bundleId ?? undefined, 'bundleId');
|
|
303
|
+
if (e)
|
|
304
|
+
return e;
|
|
305
|
+
try {
|
|
306
|
+
sessions.milestone(session, 'app_launch_start');
|
|
307
|
+
await sim.launchApp(udid, bundleId);
|
|
308
|
+
sessions.milestone(session, 'app_launch_end');
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
return qaError({ what: `Launch failed: ${String(err)}`, changedState: false, retrySafe: true, failureCode: 'BUNDLE_ID_NOT_FOUND', nextSteps: ['Confirm the app is installed (qa_ios install) and that bundleId is correct.'] });
|
|
312
|
+
}
|
|
313
|
+
session.appId = bundleId;
|
|
314
|
+
sessions.persist(session);
|
|
315
|
+
sessions.recordMutation(session, {
|
|
316
|
+
tool: 'qa_ios',
|
|
317
|
+
action: 'ios_launch',
|
|
318
|
+
risk: 'low',
|
|
319
|
+
target: { udid, bundleId },
|
|
320
|
+
consent: { required: false, approved: true },
|
|
321
|
+
status: 'executed',
|
|
322
|
+
});
|
|
323
|
+
return qaOk({ launched: true, bundleId }, `launched ${bundleId}. Use qa_screenshot / qa_assert_visual to verify.`);
|
|
324
|
+
}
|
|
325
|
+
if (action === 'terminate') {
|
|
326
|
+
const bundleId = args.bundleId ?? session.appId;
|
|
327
|
+
const e = need(bundleId ?? undefined, 'bundleId');
|
|
328
|
+
if (e)
|
|
329
|
+
return e;
|
|
330
|
+
await sim.terminateApp(udid, bundleId);
|
|
331
|
+
sessions.recordMutation(session, {
|
|
332
|
+
tool: 'qa_ios',
|
|
333
|
+
action: 'ios_terminate',
|
|
334
|
+
risk: 'low',
|
|
335
|
+
target: { udid, bundleId },
|
|
336
|
+
consent: { required: false, approved: true },
|
|
337
|
+
status: 'executed',
|
|
338
|
+
});
|
|
339
|
+
return qaOk({ terminated: true, bundleId }, `terminated ${bundleId}`);
|
|
340
|
+
}
|
|
341
|
+
if (action === 'openurl') {
|
|
342
|
+
const e = need(args.url, 'url (a deep link)');
|
|
343
|
+
if (e)
|
|
344
|
+
return e;
|
|
345
|
+
try {
|
|
346
|
+
await sim.openUrl(udid, args.url);
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
return qaError({ what: `openurl failed: ${String(err)}`, changedState: false, retrySafe: true, nextSteps: ['Check the deep-link scheme is registered by an installed app.'] });
|
|
350
|
+
}
|
|
351
|
+
sessions.addEnvChange(session, `ios openurl ${args.url}`);
|
|
352
|
+
sessions.recordMutation(session, {
|
|
353
|
+
tool: 'qa_ios',
|
|
354
|
+
action: 'ios_openurl',
|
|
355
|
+
risk: 'low',
|
|
356
|
+
target: { udid, url: args.url },
|
|
357
|
+
consent: { required: false, approved: true },
|
|
358
|
+
status: 'executed',
|
|
359
|
+
});
|
|
360
|
+
return qaOk({ opened: args.url }, `opened deep link ${args.url}`);
|
|
361
|
+
}
|
|
362
|
+
if (action === 'screenshot') {
|
|
363
|
+
if (session.sensitive)
|
|
364
|
+
return sensitiveRefusal('Screenshot');
|
|
365
|
+
try {
|
|
366
|
+
const png = await sim.screenshot(udid);
|
|
367
|
+
const n = ++session.screenshotCount;
|
|
368
|
+
const uri = sessions.saveArtifact(session, 'screenshot', `ios-${n}.png`, png, 'image/png', 'iOS simulator screenshot');
|
|
369
|
+
sessions.bump(session, 'screenshots');
|
|
370
|
+
const coordinateSpace = await captureCoordinateSpace(session.driver, png);
|
|
371
|
+
return qaOk({ uri, bytes: png.length, coordinateSpace }, `screenshot → ${uri} (${coordinateSpace.screenshot?.width}x${coordinateSpace.screenshot?.height})`);
|
|
372
|
+
}
|
|
373
|
+
catch (err) {
|
|
374
|
+
return qaError({ what: `Screenshot failed: ${String(err)}`, changedState: false, retrySafe: true, nextSteps: ['Confirm the simulator is booted (qa_ios list).'] });
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (action === 'logs') {
|
|
378
|
+
if (session.sensitive)
|
|
379
|
+
return sensitiveRefusal('iOS simulator logs');
|
|
380
|
+
const bundleId = args.bundleId ?? session.appId ?? undefined;
|
|
381
|
+
try {
|
|
382
|
+
const text = await sim.simulatorLogs(udid, { last: args.last, bundleId });
|
|
383
|
+
const uri = sessions.saveArtifact(session, 'logs', `ios-simulator-${Date.now()}.log`, text.slice(-120_000), 'text/plain', `iOS simulator logs${bundleId ? ` for ${bundleId}` : ''}`);
|
|
384
|
+
return qaOk({ uri, bytes: text.length, last: args.last ?? '5m', bundleId: bundleId ?? null }, `captured iOS simulator logs → ${uri}`);
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
return qaError({ what: `log capture failed: ${String(err)}`, changedState: false, retrySafe: true, nextSteps: ['Confirm the simulator is booted and try a shorter last range such as last:"1m".'] });
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (action === 'privacy_reset') {
|
|
391
|
+
const e = need(args.service, 'service (e.g. location, photos, camera, all)');
|
|
392
|
+
if (e)
|
|
393
|
+
return e;
|
|
394
|
+
const bundleId = args.bundleId ?? session.appId ?? undefined;
|
|
395
|
+
const gate = consumeConsent(args.consentId, args.approve, { action: 'privacy_reset', affects: { service: args.service, bundleId } });
|
|
396
|
+
if (!gate.approved) {
|
|
397
|
+
sessions.recordMutation(session, {
|
|
398
|
+
tool: 'qa_ios',
|
|
399
|
+
action: 'privacy_reset',
|
|
400
|
+
risk: 'low',
|
|
401
|
+
target: { udid, service: args.service, bundleId: bundleId ?? null },
|
|
402
|
+
consent: { required: true, approved: false },
|
|
403
|
+
status: 'requested',
|
|
404
|
+
});
|
|
405
|
+
return requireConsent({ action: 'privacy_reset', risk: 'low', exactCommand: `xcrun simctl privacy ${udid} reset ${args.service}${bundleId ? ` ${bundleId}` : ''}`, affects: { service: args.service, bundleId }, explain: `Reset the "${args.service}" privacy permission${bundleId ? ` for ${bundleId}` : ''} on the simulator?` });
|
|
406
|
+
}
|
|
407
|
+
sessions.recordMutation(session, {
|
|
408
|
+
tool: 'qa_ios',
|
|
409
|
+
action: 'privacy_reset',
|
|
410
|
+
risk: 'low',
|
|
411
|
+
target: { udid, service: args.service, bundleId: bundleId ?? null },
|
|
412
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
413
|
+
status: 'approved',
|
|
414
|
+
});
|
|
415
|
+
try {
|
|
416
|
+
await sim.privacyReset(udid, args.service, bundleId);
|
|
417
|
+
}
|
|
418
|
+
catch (err) {
|
|
419
|
+
sessions.recordMutation(session, {
|
|
420
|
+
tool: 'qa_ios',
|
|
421
|
+
action: 'privacy_reset',
|
|
422
|
+
risk: 'low',
|
|
423
|
+
target: { udid, service: args.service, bundleId: bundleId ?? null },
|
|
424
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
425
|
+
status: 'blocked',
|
|
426
|
+
detail: String(err),
|
|
427
|
+
});
|
|
428
|
+
return qaError({ what: `privacy reset failed: ${String(err)}`, changedState: false, retrySafe: true, nextSteps: ['Check the service name (location/photos/camera/contacts/all).'] });
|
|
429
|
+
}
|
|
430
|
+
sessions.addEnvChange(session, `ios privacy reset ${args.service}${bundleId ? ` ${bundleId}` : ''}`);
|
|
431
|
+
sessions.recordMutation(session, {
|
|
432
|
+
tool: 'qa_ios',
|
|
433
|
+
action: 'privacy_reset',
|
|
434
|
+
risk: 'low',
|
|
435
|
+
target: { udid, service: args.service, bundleId: bundleId ?? null },
|
|
436
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
437
|
+
status: 'executed',
|
|
438
|
+
});
|
|
439
|
+
return qaOk({ service: args.service, bundleId: bundleId ?? null, reset: true }, `reset privacy: ${args.service}`);
|
|
440
|
+
}
|
|
441
|
+
// action === 'erase'
|
|
442
|
+
{
|
|
443
|
+
const target = args.device ?? udid;
|
|
444
|
+
const gate = consumeConsent(args.consentId, args.approve, { action: 'erase_device', affects: { udid: target } });
|
|
445
|
+
if (!gate.approved) {
|
|
446
|
+
sessions.recordMutation(session, {
|
|
447
|
+
tool: 'qa_ios',
|
|
448
|
+
action: 'erase_device',
|
|
449
|
+
risk: 'high',
|
|
450
|
+
target: { udid: target },
|
|
451
|
+
consent: { required: true, approved: false },
|
|
452
|
+
status: 'requested',
|
|
453
|
+
});
|
|
454
|
+
return requireConsent({ action: 'erase_device', risk: 'high', exactCommand: `xcrun simctl erase ${target}`, affects: { udid: target }, explain: `Erase all content and settings on simulator ${target}? This wipes installed apps and data.` });
|
|
455
|
+
}
|
|
456
|
+
sessions.recordMutation(session, {
|
|
457
|
+
tool: 'qa_ios',
|
|
458
|
+
action: 'erase_device',
|
|
459
|
+
risk: 'high',
|
|
460
|
+
target: { udid: target },
|
|
461
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
462
|
+
status: 'approved',
|
|
463
|
+
});
|
|
464
|
+
try {
|
|
465
|
+
await sim.erase(target);
|
|
466
|
+
}
|
|
467
|
+
catch (err) {
|
|
468
|
+
sessions.recordMutation(session, {
|
|
469
|
+
tool: 'qa_ios',
|
|
470
|
+
action: 'erase_device',
|
|
471
|
+
risk: 'high',
|
|
472
|
+
target: { udid: target },
|
|
473
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
474
|
+
status: 'blocked',
|
|
475
|
+
detail: String(err),
|
|
476
|
+
});
|
|
477
|
+
return qaError({ what: `erase failed: ${String(err)}`, changedState: true, retrySafe: true, nextSteps: ['Shut the simulator down and retry.'] });
|
|
478
|
+
}
|
|
479
|
+
sessions.addEnvChange(session, `ios erase ${target}`);
|
|
480
|
+
sessions.recordMutation(session, {
|
|
481
|
+
tool: 'qa_ios',
|
|
482
|
+
action: 'erase_device',
|
|
483
|
+
risk: 'high',
|
|
484
|
+
target: { udid: target },
|
|
485
|
+
consent: { required: true, consentId: args.consentId, approved: true },
|
|
486
|
+
status: 'executed',
|
|
487
|
+
});
|
|
488
|
+
return qaOk({ erased: target }, `erased simulator ${target} (it is now shut down — qa_ios boot to use it again).`);
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
//# sourceMappingURL=ios.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ios.js","sourceRoot":"","sources":["../../src/tools/ios.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// qa_job_status — poll a long-running job (boot/install).
|
|
2
|
+
// Lets a client reconnect after a tool-call timeout instead of restarting the work.
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { qaOk, qaError } from '../lib/result.js';
|
|
5
|
+
import { progressLine } from '../session/progress.js';
|
|
6
|
+
export function registerJobs(server, sessions) {
|
|
7
|
+
server.registerTool('qa_job_status', {
|
|
8
|
+
title: 'Job status',
|
|
9
|
+
description: 'Status of a long-running job (e.g. from qa_prepare_target / qa_test_this execute): running/done/failed/cancelled, the structured progressDetail (phase/elapsed/statusText/nextExpected/logUri/userActionRequired), and the result/error when finished. For a qa_test_this execute job the result carries the terminal state (completed/blocked/unsafe), reportUri, suite, smoke, and health.',
|
|
10
|
+
inputSchema: { sessionId: z.string(), jobId: z.string() },
|
|
11
|
+
}, async ({ sessionId, jobId }) => {
|
|
12
|
+
const job = sessions.get(sessionId)?.jobs.get(jobId);
|
|
13
|
+
if (!job) {
|
|
14
|
+
return qaError({ what: `Unknown job ${jobId}`, changedState: false, retrySafe: true, nextSteps: ['Check the jobId returned by qa_prepare_target.'] });
|
|
15
|
+
}
|
|
16
|
+
const progLine = progressLine(job.progressDetail);
|
|
17
|
+
return qaOk({ jobId: job.jobId, kind: job.kind, status: job.status, progress: job.progress, progressDetail: job.progressDetail ?? null, error: job.error, result: job.result, artifactUris: job.artifactUris }, `job ${job.jobId} [${job.kind}] = ${job.status}${progLine ? `\n ${progLine}` : job.progress ? ` (${job.progress})` : ''}${job.resultText ? `\n${job.resultText}` : ''}${job.error ? `\nerror: ${job.error}` : ''}`);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/tools/jobs.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,oFAAoF;AAEpF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,MAAM,UAAU,YAAY,CAAC,MAAiB,EAAE,QAAsB;IACpE,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,KAAK,EAAE,YAAY;QACnB,WAAW,EAAE,8XAA8X;QAC3Y,WAAW,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;KAC1D,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;QAC7B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACrD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,eAAe,KAAK,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,gDAAgD,CAAC,EAAE,CAAC,CAAC;QACxJ,CAAC;QACD,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAClD,OAAO,IAAI,CACT,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,CAAC,cAAc,IAAI,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,YAAY,EAAE,EAClM,OAAO,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,QAAQ,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACpN,CAAC;IACJ,CAAC,CACF,CAAC;AAEJ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Network restore helpers retained for flows that temporarily change device connectivity.
|
|
2
|
+
/** Restore network to the recorded original state. Exported for report/session-end use. */
|
|
3
|
+
export async function restoreNetwork(sessions, session, d) {
|
|
4
|
+
if (!session.network?.changed)
|
|
5
|
+
return null;
|
|
6
|
+
const original = session.network.originalAirplane;
|
|
7
|
+
await d.setAirplane(original);
|
|
8
|
+
sessions.addEnvChange(session, `network restored (airplane=${original})`);
|
|
9
|
+
sessions.recordMutation(session, {
|
|
10
|
+
tool: 'qa_report',
|
|
11
|
+
action: 'network_restore',
|
|
12
|
+
risk: 'low',
|
|
13
|
+
target: { toAirplane: original },
|
|
14
|
+
consent: { required: false, approved: true },
|
|
15
|
+
status: 'restored',
|
|
16
|
+
detail: `restored airplane=${original}`,
|
|
17
|
+
});
|
|
18
|
+
session.network = { changed: false, originalAirplane: original };
|
|
19
|
+
sessions.persist(session);
|
|
20
|
+
return `restored (airplane=${original})`;
|
|
21
|
+
}
|
|
22
|
+
/** Best-effort restore of every session that changed the network, for server shutdown. */
|
|
23
|
+
export async function restoreAllNetwork(sessions) {
|
|
24
|
+
const { DirectDriver } = await import('../drivers/DirectDriver.js');
|
|
25
|
+
for (const s of sessions.list()) {
|
|
26
|
+
if (!s.network?.changed)
|
|
27
|
+
continue;
|
|
28
|
+
const d = s.driver ?? (s.device ? new DirectDriver(s.device) : undefined);
|
|
29
|
+
if (!d)
|
|
30
|
+
continue;
|
|
31
|
+
try {
|
|
32
|
+
await d.setAirplane(s.network.originalAirplane);
|
|
33
|
+
sessions.recordMutation(s, {
|
|
34
|
+
tool: 'swipium_shutdown',
|
|
35
|
+
action: 'network_restore',
|
|
36
|
+
risk: 'low',
|
|
37
|
+
target: { toAirplane: s.network.originalAirplane, shutdown: true },
|
|
38
|
+
consent: { required: false, approved: true },
|
|
39
|
+
status: 'restored',
|
|
40
|
+
detail: 'best-effort restore on shutdown',
|
|
41
|
+
});
|
|
42
|
+
s.network = { changed: false, originalAirplane: s.network.originalAirplane };
|
|
43
|
+
sessions.persist(s);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
/* best-effort on shutdown */
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/tools/network.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAK1F,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAsB,EAAE,OAAgB,EAAE,CAAS;IACtF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;IAClD,MAAM,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,8BAA8B,QAAQ,GAAG,CAAC,CAAC;IAC1E,QAAQ,CAAC,cAAc,CAAC,OAAO,EAAE;QAC/B,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,iBAAiB;QACzB,IAAI,EAAE,KAAK;QACX,MAAM,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE;QAChC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC5C,MAAM,EAAE,UAAU;QAClB,MAAM,EAAE,qBAAqB,QAAQ,EAAE;KACxC,CAAC,CAAC;IACH,OAAO,CAAC,OAAO,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,CAAC;IACjE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,OAAO,sBAAsB,QAAQ,GAAG,CAAC;AAC3C,CAAC;AAED,0FAA0F;AAC1F,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,QAAsB;IAC5D,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;IACpE,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;QAChC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO;YAAE,SAAS;QAClC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC1E,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,IAAI,CAAC;YACH,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;YAChD,QAAQ,CAAC,cAAc,CAAC,CAAC,EAAE;gBACzB,IAAI,EAAE,kBAAkB;gBACxB,MAAM,EAAE,iBAAiB;gBACzB,IAAI,EAAE,KAAK;gBACX,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAClE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE;gBAC5C,MAAM,EAAE,UAAU;gBAClB,MAAM,EAAE,iCAAiC;aAC1C,CAAC,CAAC;YACH,CAAC,CAAC,OAAO,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7E,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,6BAA6B;QAC/B,CAAC;IACH,CAAC;AACH,CAAC"}
|