feat(sdks): fold SDK monorepo in-tree under sdks/ - #819
Conversation
Bring the standalone go-ios SDK monorepo into this repo under a top-level
sdks/ directory: the TypeSpec -> OpenAPI 3.1 spec, the Python/TypeScript/
Java/C# client SDKs, and the MCP server, plus their docs and scripts.
The SDK CI is relocated to repo-root .github/workflows/ (so it runs) but
scoped to sdks/** and renamed to avoid colliding with go-ios's existing
workflows:
- sdks.yml (validation: spec compile + per-package build/test)
- sdks-publish-{typescript,python,java,csharp}.yml (tag/dispatch-gated,
inert; publish tags kept prefixed as csharp-v* / python-v* so they never
collide with go-ios's v* release tags)
go build ./... and go test ./... are unaffected (no Go sources under sdks/,
go.work/go.mod untouched). Build artifacts under sdks/ are ignored via the
nested sdks/.gitignore and per-package ignores; the committed generated
client code stays tracked.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
| name: TypeScript SDK build + test | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: sdks/packages/typescript | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "22" | ||
| cache: npm | ||
| cache-dependency-path: sdks/packages/typescript/package-lock.json | ||
| - run: npm ci | ||
| - run: npx tsc --noEmit | ||
| - run: npm run build | ||
| - run: npm test | ||
|
|
||
| mcp: |
| name: MCP server build + test | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: sdks/packages/mcp | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "22" | ||
| cache: npm | ||
| cache-dependency-path: sdks/packages/mcp/package-lock.json | ||
| - run: npm ci | ||
| - run: npx tsc --noEmit | ||
| - run: npm run build | ||
| - run: npm test | ||
|
|
||
| python: |
| name: Python SDK test (3.9-3.13) + types | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: sdks/packages/python | ||
| strategy: | ||
| matrix: | ||
| python-version: ["3.9", "3.13"] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@v5 | ||
| - name: Set up Python ${{ matrix.python-version }} | ||
| run: uv python install ${{ matrix.python-version }} | ||
| - name: Sync deps | ||
| run: uv sync --all-extras --dev | ||
| - name: Test | ||
| run: uv run pytest | ||
| - name: Type check (facade) | ||
| run: uv run mypy src/go_ios_sdk --exclude '_generated' | ||
| continue-on-error: false | ||
|
|
||
| csharp: |
| name: C# SDK build + test | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: sdks/packages/csharp | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-dotnet@v4 | ||
| with: | ||
| dotnet-version: "8.0.x" | ||
| - run: dotnet build -c Release | ||
| - run: dotnet test -c Release --no-build | ||
|
|
||
| java: |
| name: Java SDK compile + test | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: sdks/packages/java | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-java@v4 | ||
| with: | ||
| distribution: temurin | ||
| java-version: "17" | ||
| - name: Compile + test (javac + JUnit console) | ||
| run: bash scripts/verify.sh |
Replace the four inert per-package publish workflows with ONE
dispatch-only release pipeline for all five SDKs, generated from one
OpenAPI spec and versioned in lockstep.
- sdks/scripts/set-version.sh stamps one version into every manifest
(ts/mcp package.json, python pyproject.toml, java pom.xml, csharp
csproj) and fails loudly if any manifest is not updated.
- release-sdks.yml: workflow_dispatch only (version + dry_run, default
true). Build+test all five before any publish. Each ecosystem publish
is gated twice: dry_run does a real dry-run (npm --dry-run, twine
check, mvn verify, dotnet pack) with no upload; a registry-armed guard
makes even a real run self-skip until the registry is configured.
npm via OIDC (no token), PyPI via trusted publishing, Maven Central via
central-publishing-maven-plugin + GPG, NuGet via dotnet nuget push.
git tag sdk-v<version> + GitHub release only after all publishes
succeed and not dry_run.
- Delete sdks-publish-{typescript,python,csharp,java}.yml; keep sdks.yml
CI as-is (comment updated).
- sdks/docs/RELEASING.md: how to cut a release (dry_run first),
lockstep model, and the registry prerequisites; until armed, real
publishes self-skip.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Added: consolidated dispatch-only SDK release pipelineReplaced the four inert per-package publish workflows with one dispatch-only pipeline,
|
Extend the in-tree TypeSpec spec from the spec-v2 parity surface (80 ops /
65 paths) to the feature-complete daemon surface on feature/restapi-complete:
125 operations across 107 paths under /api/v1, a 1:1 match to the daemon's
registered routes (excluding /healthz, /readyz, /swagger).
Adds the 45 new operations from Waves 1-4 as new route files:
- routes-diagnostics.tsp (w1a): diskspace, ip, rsd, battery/registry; and a
`?domain=` query on the existing /lockdown op.
- routes-accessibility.tsp (w1b): GET/PUT voiceover, GET/PUT zoom, POST ax/audit,
GET ax, PUT setlocation/gpx (multipart).
- routes-fsync.tsp (w1c): fsync ls/tree/pull(binary)/push(raw|multipart)/rm/mkdir
(?path=,?bundleID=), cloudconfig, and host-scoped /prepare/skip-options.
- routes-webinspector.tsp (w1d): pages, launch, eval (424 when disabled).
- routes-ui.tsp (w2): tap/swipe/longpress/type/button/api, app launch/terminate/
foreground, screenshot(PNG)/source/size/orientation/status, PUT orientation;
proxied to a forwarded WDA/DeviceKit backend (backend/wdaUrl/timeout params).
- routes-streams.tsp (w3): ui/stream, screenshot/stream, pcap modeled as BINARY
byte streams (x-stream: binary, x-content-type), NOT text/event-stream SSE.
- routes-sign.tsp (w4): host-scoped /sign/{certificate,provision,app} and
/prepare/create-cert, plus device-scoped /device/{udid}/prepare (multipart).
All request/response models added to models.tsp mirroring the Go structs; adds
413/424/501 error models. Re-emits canonical OpenAPI 3.1 + 3.2 via regen.sh and
documents the new groups and binary-vs-SSE distinction in docs/DESIGN.md.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
…ublishable
Extend the curated MCP tool set (31 -> 44) for the feature-complete daemon and
flip the package to publishable.
Publishable:
- remove `private: true`; add repo/homepage/bugs/keywords metadata and
`publishConfig` { access: public, provenance: true } (matches @go-ios/typescript).
New tools:
- UI automation (drive the device via a forwarded WDA/DeviceKit backend):
ui_tap, ui_swipe, ui_type, ui_press_button, ui_source (view hierarchy, bounded),
ui_screenshot (single frame via UI backend), ui_app_launch, ui_app_terminate.
All take backend/wdaUrl/timeout; descriptions document the run_wda + forward
prerequisite.
- Diagnostics: device_diskspace, device_ip.
- Files (read-only over AFC): list_device_files, read_file (bounded 512 KiB).
- Location: set_location_gpx (multipart upload).
- Web debugging: list_webinspector_pages, webinspector_eval (JS eval).
Client: getBytes now takes query params; getTextBounded takes an accept override;
friendly errors for 424/501/502 (UI/WebInspector prerequisites).
Deliberately omitted: sign/*, prepare (host-local/secret-handling), erase
(destructive), raw pcap/screenshot/ui video streams (too large; single-frame or
bounded-capture instead), fsync/files writes+deletes. reboot/shutdown stay
DISRUPTIVE-flagged.
Tests: registration covers new tools via CURATED_TOOL_NAMES + udid invariant;
added UI-prerequisite assertions and handler tests (ui_tap/ui_type/ui_source/
ui_screenshot, device_diskspace, list_device_files, read_file, webinspector_eval,
424 surfacing). 37 tests green; build + tsc --noEmit clean. README updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Regenerate the hey-api client from the 125-op openapi.yaml and extend the ergonomic facade with the new groups, keeping the existing shape and cross-language-consistent naming: - device: diskSpace/ip/rsd/batteryRegistry/cloudConfig; lockdown(domain?); ax/axAudit; voiceOver/setVoiceOver; zoom/setZoom; setLocationGpx; prepare - device.fsync: ls/tree/pull/push/rm/mkdir (bundleId-scoped) - device.webinspector: pages/launch/eval - device.ui: tap/swipe/longPress/type/button/screenshot/source/size/ orientation/setOrientation/status/api + app.launch|terminate|foreground - binary streams (raw bytes, not SSE): device.ui.stream, device.screenshotStream, device.pcap via a new reusable BinaryStream helper over Response.body with AbortSignal support - client.sign: certificate/provision/app; client.prepare: createCert/skipOptions Add vitest coverage for the new groups plus binary-stream tests (mock chunked body iteration, mid-stream + pre-aborted cancellation, error mapping); existing SSE tests still pass. Update the README. build/test/tsc all green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Regenerate the vendored openapi-python-client (0.26.1) from the 125-operation spec and extend both the sync and async facades with the new v3 groups: - device diagnostics/network: disk_space, ip, rsd, battery_registry, and a domain-scoped lockdown(domain=...) - accessibility/location: voice_over/set_voice_over, zoom/set_zoom, ax, ax_audit, set_location_gpx (multipart) - AFC fsync: ls/tree/pull/push/rm/mkdir (bundle_id -> bundleID) and cloud_config - webinspector: pages/launch/eval - ui automation: tap/swipe/long_press/type/button/screenshot/source/size/ orientation/set_orientation/status/api and ui.app.launch|terminate|foreground, all with backend/wda_url/timeout kwargs - binary streams (raw bytes, NOT SSE): ui.stream, screenshot_stream, pcap via a reusable byte-chunk stream helper (sync generator + async generator over httpx streaming, cancelable) - device-scoped prepare (multipart) and host-scoped sign.certificate/provision/app + prepare.create_cert/skip_options Adds facade tests for representative new groups and binary streams (including a chunked-transport boundary/cancel test and async cancellation), plus README docs. pytest (69) green; mypy and ruff clean on the facade. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Regenerate the low-level client from the 125-op OpenAPI spec and add an ergonomic hand-written facade over java.net.http covering the complete go-ios REST surface, matching the TS/Python/C# SDK naming. New facade groups on top of the base ~80 ops: - Device: diskSpace/ip/rsd/batteryRegistry, lockdown()/lockdown(domain), voiceOver/setVoiceOver, zoom/setZoom, ax/axAudit, setLocationGpx, cloudConfig, prepare (multipart). - Device.fsync(): ls/tree/pull(->byte[])/push/rm/mkdir (path + optional bundleId). - Device.webinspector(): pages/launch/eval. - Device.ui(): tap/swipe/longPress/type/button/screenshot(->byte[])/source/ size/orientation/setOrientation/status/app launch|terminate|foreground/api, with backend/wdaUrl/timeout via Ui.Options. - Binary streams (x-stream: binary, not SSE): Device.ui().stream(), screenshotStream(), pcap() return a closeable BinaryStream (InputStream). - Host-scoped: client.sign().app/certificate(->byte[])/provision(), client.prepare().createCert()/skipOptions(). Streaming: typed SseReader (syslog/notifications/ostrace/listen/sysmontap/ job logs) plus a separate raw BinaryStream seam. Binary/multipart/octet-stream endpoints go through the RawHttp helper for byte-exact wire formats. Tests: add V3SurfaceHttpTest (new groups + a chunked binary-stream test); existing facade + SSE suites still pass. 41 tests green via scripts/verify.sh (javac --release 17 + JUnit console; no Maven). Update README to the 125-op surface. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Regenerate the low-level csharp client from the 125-op spec (regen.sh; anyOf-Heartbeat dangling-comma post-gen fix still applies clean) and extend the hand-written facade with the new groups, matching the shared SDK API shape: - DeviceClient: DiskSpace/Ip/Rsd/BatteryRegistry, VoiceOver/Zoom (+setters), AxAudit/Ax, SetLocationGpx, CloudConfig, Prepare; LockdownAsync(domain). - DeviceClient.Fsync: Ls/Tree/Pull(->byte[])/Push/Rm/Mkdir (path + bundleId). - DeviceClient.WebInspector: Pages/Launch/Eval. - DeviceClient.Ui: Tap/Swipe/LongPress/Type/Button/Screenshot(->byte[])/Source/ Size/Orientation(+set)/Status/App launch|terminate|foreground/Api, with backend/wdaUrl/timeout Options. - Raw binary streams (BinaryStream : Stream via ResponseHeadersRead, token-aware, disposable): Ui.Stream, ScreenshotStream, Pcap. Separate from the SseReader. - Host: client.Sign.Certificate(->byte[])/Provision/App(->byte[]); client.Prepare.CreateCert/SkipOptions. xUnit tests cover the new groups plus binary-stream chunked-read and cancellation; SSE tests unchanged. README updated. dotnet build/test -c Release green (50/50). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
…tignore The MCP package dropped private:true, so wire it into release-sdks.yml's publish-npm job: build + npm publish (OIDC, --access public, provenance) for sdks/packages/mcp, dry-run/OIDC-guarded exactly like the TypeScript publish. Removed the stale "mcp is private" note. The job already depends on build-mcp. Also harden sdks/packages/java/.gitignore: the repo-root bare `main` pattern (for the compiled go-ios binary) also matched this Maven package's src/main/, which silently untracked the hand-written Java facade sources. Add !src/** negations so the SDK sources are always tracked. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
v3 integration: full 125-endpoint SDK surfaceMerged the v3 spec + all five package regens onto this branch and verified everything green. Coverage
Fixes in this batch
Verification (all green, local toolchains)
|
Add examples/GoIos.Examples: a heavily-commented console project that references the SDK facade and doubles as documentation and a pre-release smoke test. Env-configured (GO_IOS_BASE_URL / GO_IOS_API_KEY / GO_IOS_UDID / RUN_UI). Covers list-devices, device-info, list-apps, screenshot, stream-syslog, and an optional (RUN_UI=1) ui-automation example that skips gracefully when WDA is unreachable. Program.cs dispatches by arg; `run-all` runs examples 1-5 in sequence, returns non-zero on any exception, and prints SKIP (not FAIL) for no-device / no-WDA steps. Adds examples/run.sh, examples/README.md, and an Examples section in the package README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Add sdks/packages/mcp/examples/: paste-ready + annotated MCP client configs (Claude Desktop, generic), a stdio `list-tools` script that spawns the built server and introspects its curated tool set (no device/daemon needed), an optional `call-tool` that exercises list_devices against a running daemon (SKIPs gracefully if unreachable), and a `run-all` runner wired to `npm run examples` that asserts the exact 44-tool set is present and runs call-tool only when GO_IOS_API_KEY is set and the daemon is reachable. README documents it and the package README links to it. Adds tsx as a devDependency; the examples dir is not published (package `files` is dist + README only). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
…nner Add sdks/packages/python/examples/: standalone, heavily-commented scripts that double as docs and as a pre-release smoke test against a live go-ios daemon. - 01_list_devices, 02_device_info, 03_list_apps, 04_screenshot, 05_stream_syslog (SSE, bounded), 06_async_stream (AsyncIosClient sysmontap, bounded), 07_ui_automation (optional; skips if WDA backend unreachable). - run_all.py runs 01-06 in sequence (07 only when RUN_UI=1); exits non-zero on any unexpected exception, prints SKIP (exit 0) for no-device / unreachable-UI. - Env-configured: GO_IOS_BASE_URL (default http://localhost:8080), GO_IOS_API_KEY (required; helpful non-zero exit when unset), GO_IOS_UDID (optional). - examples/README.md documents daemon setup + how to run; linked from package README via a new Examples section. Verified: py_compile clean, ruff/mypy/pytest green; runner exit behavior and no-device SKIP path checked against a mock daemon. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Add a heavily-commented examples suite under sdks/packages/java/examples/ that doubles as documentation and a pre-release smoke test. Each class is a standalone main configured via GO_IOS_BASE_URL / GO_IOS_API_KEY / GO_IOS_UDID: - ListDevicesExample, DeviceInfoExample, ListAppsExample, ScreenshotExample, StreamSyslogExample (SSE via SseReader), and an optional UiAutomationExample (WDA tap+type, gated on RUN_UI=1, skips gracefully when unreachable). - RunAllExamples runs 1-5 in sequence and exits non-zero on any exception; device-dependent steps print SKIP when no device is attached so the suite passes on a device-less daemon. Missing GO_IOS_API_KEY -> helpful message + exit 1. - run.sh compiles the SDK + examples via javac (mirroring scripts/verify.sh's classpath) and runs the driver; --compile-only builds without a daemon. - examples/README.md documents daemon startup, env, and compile/run; linked from the package README's new "Examples" section. Verified: examples compile via javac (JDK 17+); scripts/verify.sh still green; go build ./... clean. Build output (examples/target/, .tools/) is already ignored by the package .gitignore, so no .gitignore changes were needed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Add sdks/packages/typescript/examples/: standalone, heavily-commented .ts scripts that double as docs and a pre-release smoke test. Cover the core public API (list devices, device info, list apps, screenshot, SSE syslog stream, opt-in UI automation), all configured via env vars (GO_IOS_BASE_URL/GO_IOS_API_KEY/GO_IOS_UDID). run-all.ts runs 01-05 (06 only when RUN_UI=1) sharing one client and exits non-zero if any example genuinely fails; device-dependent steps that can't run (no device / UI backend not forwarded) SKIP without failing. Missing GO_IOS_API_KEY prints help and exits non-zero. Add tsx devDep, `examples` + `examples:build` scripts, examples/tsconfig for typechecking, examples/README.md, and an Examples section in the package README. Ignore the screenshot.png artifact. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Integrate the five per-language examples suites (typescript, python, java, csharp, mcp) and tie them together: - sdks/docs/EXAMPLES.md: top-level overview (docs + pre-release smoke test), per-language index, shared GO_IOS_BASE_URL/GO_IOS_API_KEY/GO_IOS_UDID/RUN_UI convention, how to run them all. Linked from sdks/README.md. Documents the canonical daemon port (8080, matching the daemon's --addr default) and the SDK-library-vs-daemon default discrepancy (libraries default to :60105 from the spec servers URL) for a follow-up reconcile. - sdks.yml: add the device-free MCP list-tools smoke check (npm run examples) to the mcp job so a broken MCP server fails CI. - verify-sdk-examples.yml: new dispatch-only, farm-gated workflow that runs every SDK's example runner against a live go-ios REST daemon + device. Inert until the full REST daemon lands on main (#817/#821); the daemon-start step is a documented placeholder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Integrated the five example suites (typescript, python, java, csharp, mcp) into this PR — each merged cleanly (every branch touched only its own
Local verification: MCP |
| name: Run every SDK example runner against a live daemon | ||
| # Runs on the self-hosted device farm (office01 / ganjalf), reusing the same | ||
| # runner labels as real-device.yml. Until #817/#821 land and the daemon is | ||
| # deployable there, do not dispatch this. | ||
| runs-on: [self-hosted, macOS] | ||
| env: | ||
| GO_IOS_BASE_URL: ${{ vars.GO_IOS_BASE_URL || 'http://localhost:8080' }} | ||
| GO_IOS_API_KEY: ${{ secrets.GO_IOS_API_KEY }} | ||
| RUN_UI: ${{ inputs.run_ui && '1' || '' }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| # ───────────────────────────────────────────────────────────────────── | ||
| # PLACEHOLDER — activate once the full REST daemon is on main (#817/#821). | ||
| # | ||
| # The daemon does not exist on `main` yet, so we cannot build/start it | ||
| # here. When it lands, replace this step with something like: | ||
| # | ||
| # - name: Build & start go-ios REST daemon | ||
| # run: | | ||
| # go build -o /tmp/ios ./ | ||
| # /tmp/ios api --api-key "$GO_IOS_API_KEY" --addr :8080 & | ||
| # # wait until GET $GO_IOS_BASE_URL/health responds | ||
| # for i in $(seq 1 30); do | ||
| # curl -fsS -H "Authorization: Bearer $GO_IOS_API_KEY" \ | ||
| # "$GO_IOS_BASE_URL/api/v1/health" && break || sleep 1 | ||
| # done | ||
| # | ||
| # (Default bind address is :8080 — see restapi/api/server.go and | ||
| # sdks/docs/EXAMPLES.md.) | ||
| # ───────────────────────────────────────────────────────────────────── | ||
| - name: Start go-ios REST daemon (PLACEHOLDER — see #817/#821) | ||
| run: | | ||
| echo "::error::verify-sdk-examples is inert until the full go-ios REST daemon lands on main (#817/#821)." | ||
| echo "Fill in the daemon-start step above and remove this guard once the daemon is deployable on the farm." | ||
| exit 1 | ||
|
|
||
| # --- Language toolchains (kept ready for when the gate above is removed) --- | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "22" | ||
| - uses: astral-sh/setup-uv@v5 | ||
| - uses: actions/setup-java@v4 | ||
| with: | ||
| distribution: temurin | ||
| java-version: "17" | ||
| - uses: actions/setup-dotnet@v4 | ||
| with: | ||
| dotnet-version: "8.0.x" | ||
|
|
||
| # --- Run each SDK's example runner; any non-zero exit fails the job --- | ||
| - name: TypeScript examples | ||
| working-directory: sdks/packages/typescript | ||
| run: npm ci && npm run examples | ||
|
|
||
| - name: Python examples | ||
| working-directory: sdks/packages/python | ||
| run: uv sync --all-extras && uv run python examples/run_all.py | ||
|
|
||
| - name: Java examples | ||
| working-directory: sdks/packages/java | ||
| run: bash examples/run.sh | ||
|
|
||
| - name: C# examples | ||
| working-directory: sdks/packages/csharp | ||
| run: dotnet run --project examples/GoIos.Examples -- run-all | ||
|
|
||
| - name: MCP examples (list-tools + call-tool against the live daemon) | ||
| working-directory: sdks/packages/mcp | ||
| run: npm ci && npm run build && npm run examples |
Make IosClient's baseUrl optional. Resolution order: explicit baseUrl option (verbatim) > GO_IOS_BASE_URL env > discovery of the local daemon (<GO_IOS_HOME | ~/.go-ios>/rest-api.json baseUrl) > clear throw. Adds src/discovery.ts (home resolution + sync read/parse of rest-api.json) and discovery unit tests; updates the README to document discovery. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Make baseUrl optional on IosClient.Builder. When it is not set explicitly, resolve the daemon endpoint in order: explicit .baseUrl() > GO_IOS_BASE_URL env > discovery of <home>/rest-api.json (home = GO_IOS_HOME or ~/.go-ios) > IosDiscoveryException naming the expected path. Add a Discovery class (with an injectable env/system-property seam for tests) and an IosDiscoveryException. apiKey handling is unchanged and never read from the discovery file. Adds DiscoveryTest and updates the README. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
…ort) Make IosClientOptions.BaseUrl optional and resolve the daemon address in order: explicit Options.BaseUrl > GO_IOS_BASE_URL env > discovery of <home>/rest-api.json > DaemonNotFoundException. Add a Discovery class (home = GO_IOS_HOME or ~/.go-ios; reads baseUrl via System.Text.Json) and a parameterless IosClient() ctor. ApiKey unchanged. Adds xUnit discovery tests (temp GO_IOS_HOME + rest-api.json) and updates the README with a "Connecting (daemon discovery)" section. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Make base_url optional on IosClient/AsyncIosClient. Resolution order: explicit base_url arg > GO_IOS_BASE_URL env > discovery file (<GO_IOS_HOME or ~/.go-ios>/rest-api.json baseUrl) > clear DiscoveryError. api_key now also falls back to GO_IOS_API_KEY. Adds discovery.py (home resolution + read/parse of rest-api.json, with a stale-pid hint) and discovery tests. Examples default to discovery when GO_IOS_BASE_URL is unset. README/examples docs updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
…daemon The Python examples already default to discovery. Do the same for the TypeScript, Java, and C# examples: when GO_IOS_BASE_URL is unset, construct the client with no baseUrl so the SDK auto-discovers the local daemon via ~/.go-ios/rest-api.json — no more hardcoded http://localhost:8080 fallback. Update each examples/README and sdks/docs/EXAMPLES.md: the daemon now uses an ephemeral loopback port and the SDKs auto-discover it (resolution order: explicit baseUrl > GO_IOS_BASE_URL > discovery file > error). Documents that the earlier SDK-default (:60105) vs daemon (:8080) mismatch is resolved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Integrated the four port-discovery branches (discovery/typescript, discovery/python, discovery/java, discovery/csharp) into this PR — all merged cleanly (each touched only its own All 4 SDKs now auto-discover the local daemon via Examples harmonized: TS ( Pairs with daemon PR #825 (ephemeral port + discovery-file writer). Verification (local): |
What & why
The official go-ios client SDKs (Python, TypeScript, Java, C#) and the MCP server are generated from a single TypeSpec → OpenAPI 3.1 spec (80 operations). Until now they lived in a separate
go-ios-sdksmonorepo. This PR folds that monorepo in-tree under a top-levelsdks/directory so the spec, generated clients, MCP server, and their CI travel with go-ios itself.Only committed files were brought over (via
git archive) — nonode_modules,dist,.venv,bin,obj,target, ortsp-output. The committed generated client code (src/generated,_generated,generated/,src/Generated) stays tracked; the nestedsdks/.gitignore+ per-package ignores (with their re-negations) handle this.Layout
The root
README.mdgains a brief SDKs & MCP section pointing atsdks/.CI — scoped to
sdks/**The SDK workflows must live at repo-root
.github/workflows/to run, but are scoped tosdks/**and renamed so they never collide with go-ios's existing workflows. No existing go-ios workflow is modified — only these are added:sdks.ymlsdks/**sdks-publish-typescript.ymlworkflow_dispatchonlysdks-publish-python.ymlsdks/packages/python/**, tagpython-v*, dispatchpython-v*tag / opt-in dispatchsdks-publish-csharp.ymlsdks/packages/csharp/**, tagcsharp-v*, dispatchcsharp-v*tag; NuGet push skipped without secretsdks-publish-java.ymlsdks/packages/java/**All
working-directory:,cache-dependency-path:, andpaths:were repathed undersdks/. Publish workflows stay inert — gating unchanged. Publish tags are prefixed (csharp-v*,python-v*) so they do not collide with go-ios's ownv*release tags.Verification
go build ./...— passes (no Go sources undersdks/;go.work/go.moduntouched).go test ./...— all packages pass.git status— clean; confirmed nonode_modules/dist/.venv/bin/obj/target/tsp-outputstaged (verified the ignores actively catch fabricated artifacts undersdks/).sdks/spec/openapi/openapi.yamlpresent with 80 operations; eachsdks/packages/*has source + tests + manifest; every workflow path points at a real file.For the maintainer to decide
test.yml(Go unit tests) and its chained real-device e2e, becausetest.ymlruns on all PRs. To skip those on sdks-only changes, addpaths-ignore: ['sdks/**']totest.yml— but verify branch-protection required checks first, since skipped required checks can block merges. Left to maintainer (I did not modifytest.yml).csharp-v*/python-v*to avoid colliding with go-iosv*release tags. Confirm these prefixes match your intended SDK release tagging.🤖 Generated with Claude Code
https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk