Skip to content

feat(sdk): export the client's option, result, and node types from the package root - #2959

Merged
thymikee merged 4 commits into
callstack:mainfrom
okwasniewski:oskar/sdk-root-types
Sep 25, 2026
Merged

thymikee merged 4 commits into
callstack:mainfrom
okwasniewski:oskar/sdk-root-types

Conversation

@okwasniewski

@okwasniewski okwasniewski commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

createAgentDeviceClient returns AgentDeviceClient, and every option and result type of its methods is a named type in src/client/client-types.ts, but the package root exported none of them. A consumer typed a client parameter as ReturnType<typeof createAgentDeviceClient>, a result as Awaited<ReturnType<...>>, and re-declared the node shape a snapshot returns (the @e2edev/mobile engine carries its own RawNode, RawSnapshot, and RawInstallResult for that reason).

The root now re-exports, types only:

  • every type of client-types.ts (AgentDeviceClient, AgentDeviceClientConfig, AppOpenOptions, AppOpenResult, CaptureSnapshotResult, PressOptions, AgentDeviceDevice, ...);
  • the kernel snapshot types a result is made of: SnapshotNode, RawSnapshotNode, SnapshotState, Rect, Point;
  • the error types normalizeAgentDeviceError answers in: NormalizedError, AppErrorCode, KnownAppErrorCode, AppErrorDetails, ErrorCause.
import { type AgentDeviceClient, type SnapshotNode, createAgentDeviceClient } from 'agent-device';

async function firstButton(client: AgentDeviceClient): Promise<SnapshotNode | undefined> {
  const { nodes } = await client.capture.snapshot({ interactiveOnly: true });
  return nodes?.find((node) => node.type === 'Button');
}

The JavaScript entry is unchanged. examples/sdk/client-session.ts takes AgentDeviceClient and returns AgentDeviceDevice instead of the ReturnType spelling, and the client API doc lists the type surface. 3 files.

Validation

Tested at e13a949920 (third commit: AgentArtifactsResult and CloudProviderSessionResult, which client-types.ts imports for its signatures without re-exporting, are named at the root, so the doc's "every option and result type" holds; check:quick, pnpm build, and the client-api drift guard pass on it):

  • pnpm check:affected --run --base c31cc49f6: all runnable checks passed (format, lint, typecheck, layering, fallow, build, related vitest, production exports, package gates).
  • check:production-exports reports 68 unused-export warnings, the same count as main without this change.
  • dist/src/index.d.ts after pnpm build exports 156 names, AgentDeviceClient, AppOpenResult, SnapshotNode, RawSnapshotNode, and NormalizedError among them; the JavaScript bundle is byte-identical in what it exports.
  • Types only, so no device run applies.

…e package root

createAgentDeviceClient returned AgentDeviceClient, whose option and result types
are all named in client-types.ts, but the root exported none of them. A consumer
typed a client parameter as ReturnType<typeof createAgentDeviceClient>, a result as
Awaited<ReturnType<...>>, and the nodes a snapshot returns by hand.

The root now re-exports every client type, the kernel snapshot types a result is
made of (SnapshotNode, RawSnapshotNode, SnapshotState, Rect, Point), and the error
types normalizeAgentDeviceError answers in. Types only: the JavaScript entry is
unchanged. The client example takes AgentDeviceClient and returns AgentDeviceDevice.
Copilot AI lite review requested due to automatic review settings September 25, 2026 09:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="website/docs/docs/client-api.md">

<violation number="1" location="website/docs/docs/client-api.md:37">
P2: `sessions.artifacts()` returns `AgentArtifactsResult`, but the package root does not export that type, so the “every option and result type” claim points consumers to a nonexistent root import. Export `AgentArtifactsResult` from the root or narrow this documentation claim to the types actually exported.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread website/docs/docs/client-api.md Outdated
- `createLocalArtifactAdapter(options?)`
- `AppError`, `isAgentDeviceError(error)`, `normalizeAgentDeviceError(error)`
- `centerOfRect(rect)`
- types: `AgentDeviceClient`, `AgentDeviceClientConfig`, and every option and result type of

@cubic-dev-ai cubic-dev-ai Bot Sep 25, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: sessions.artifacts() returns AgentArtifactsResult, but the package root does not export that type, so the “every option and result type” claim points consumers to a nonexistent root import. Export AgentArtifactsResult from the root or narrow this documentation claim to the types actually exported.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At website/docs/docs/client-api.md, line 37:

<comment>`sessions.artifacts()` returns `AgentArtifactsResult`, but the package root does not export that type, so the “every option and result type” claim points consumers to a nonexistent root import. Export `AgentArtifactsResult` from the root or narrow this documentation claim to the types actually exported.</comment>

<file context>
@@ -34,6 +34,11 @@ Supported public entry points for Node consumers:
   - `createLocalArtifactAdapter(options?)`
   - `AppError`, `isAgentDeviceError(error)`, `normalizeAgentDeviceError(error)`
   - `centerOfRect(rect)`
+  - types: `AgentDeviceClient`, `AgentDeviceClientConfig`, and every option and result type of
+    its methods (`AppOpenOptions`, `AppOpenResult`, `CaptureSnapshotOptions`,
+    `CaptureSnapshotResult`, `CaptureScreenshotResult`, `PressOptions`, `AgentDeviceDevice`, ...);
</file context>
Fix with cubic

Copilot AI review requested due to automatic review settings September 25, 2026 09:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…eads them

The client-api drift guard reads an example's imports one statement at a time
and strips a leading 'type ' only right after the brace, and it reads the doc's
manifest one nested bullet line at a time. The example now imports the root
types through an import type statement, and the manifest names each type on a
line that starts with a bullet, AgentDeviceDevice included, instead of on the
continuation lines of one bullet.
Copilot AI review requested due to automatic review settings September 25, 2026 09:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@thymikee

Copy link
Copy Markdown
Member

The code looks ready for human review at 6e3de21: the root re-exports the client's option, result, and node types with no naming collisions among the types it names. Not blocking: client-api.md's line saying the root exports "every option and result type" is wider than what's exported, since client-types.ts only import types AgentArtifactsResult and CloudProviderSessionResult from @agent-device/contracts/observability rather than export type-ing them, so neither name is reachable through the new root wildcard — exporting them or narrowing the doc line would close the gap, but it's fine either way.

All checks were still queued or in progress when I looked, so there's nothing to attribute yet; since this is a type-only export change plus one docs edit, the Typecheck & Package and command-docs-gate/client-api-examples-drift checks are the ones worth watching when they finish.

I confirmed by reading client-types.ts, the contracts client-* type files, and kernel/snapshot.ts and errors.ts that every named type exists and no export name collides, but I didn't run pnpm build or check:production-exports, so the PR body's counts (68 unused-export warnings, 156 exported names) are unverified by me. I also didn't run client-api-examples-drift.test.ts or tsc -p examples/sdk, so the claim that those pass is unverified by me too.
The head moved to 746d916 after this review. That commit only rewords the client-api.md list, and it still says "every option and result type", so the note above still applies.

… import

client-types.ts imports AgentArtifactsResult and CloudProviderSessionResult for
its method signatures without re-exporting them, so the root wildcard could not
reach them and the doc's 'every option and result type' was wider than the
export. The root names them explicitly.
Copilot AI review requested due to automatic review settings September 25, 2026 10:11
@okwasniewski

Copy link
Copy Markdown
Contributor Author

[claude-fable-5-1] responding on behalf of Oskar

Thanks, taken in e13a949: AgentArtifactsResult and CloudProviderSessionResult are exported from the root explicitly, so the doc line holds as written. dist/src/index.d.ts names both after pnpm build; check:quick and the client-api drift guard pass on that commit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@thymikee

Copy link
Copy Markdown
Member

Reviewed at e13a949.

export type * from '../client/client-types.ts' in src/sdk/index.ts:32 transitively re-exports @agent-device/contracts/client, which pulls in InternalRequestOptions (client-request.ts:62) and its base CommandExecutionOptions (client-request.ts:22). That file's own comment calls this the internal request envelope every client call is projected into. Before this PR it lived only inside the unpublished @agent-device/contracts package; after this PR, the published agent-device package root names it as public API, so anyone can import type { InternalRequestOptions } from 'agent-device'. Neither type is mentioned in the PR body or docs, which only advertise curated per-method Options/Result types. Once this ships, changing the daemon's internal request shape becomes a breaking change for external consumers. Can the wildcard on @agent-device/contracts/client be replaced with named re-exports of the curated per-method types, the way the kernel/errors and kernel/snapshot blocks in the same file already do, or can the internal plumbing types be moved out of that facade so the root wildcard only reaches public vocabulary?

I read the file contents at e13a949 and did not build the package; the type-only claim and re-export chain are confirmed by TypeScript module semantics, not a build artifact. I did not read every name in the 13-file, ~139-line facade — I spot-checked the ones whose names signal internal scope (InternalRequestOptions, CommandExecutionOptions, DeviceCommandBaseOptions), so there could be more.

The Smoke Tests job is still in progress; the diff only touches export type statements, an example's type annotations, and docs, so it shouldn't affect that device-facing run either way.

Before merging, it would help to confirm with the author whether making InternalRequestOptions/CommandExecutionOptions part of the public npm type surface is intentional, or whether the wildcard chain should be narrowed to match the docs' stated scope.

The root's `export type *` chain reached `@agent-device/contracts/client`, which
carried `InternalRequestOptions` and `CommandExecutionOptions`. Move both to
`request-envelope.ts` under the command façade; the client façade keeps only
`CommandRequestResult`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 25, 2026 10:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@thymikee
thymikee merged commit 8c89891 into callstack:main Sep 25, 2026
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants