Skip to content

feat: add runtime action SDK clients - #252

Open
yazcaleb wants to merge 1 commit into
masterfrom
codex/runtime-action-sdk
Open

feat: add runtime action SDK clients#252
yazcaleb wants to merge 1 commit into
masterfrom
codex/runtime-action-sdk

Conversation

@yazcaleb

Copy link
Copy Markdown
Collaborator

What changed

  • Added TypeScript SDK helpers for the iOS runtime approval API:
    • createRuntimeAction(...) posts to /v1/runtime/actions
    • waitRuntimeAction(...) long-polls /v1/runtime/actions/:id/wait
    • RuntimeActionTimeoutError preserves the last observed pending action
  • Added matching Python SDK helpers:
    • create_runtime_action(...)
    • wait_runtime_action(...)
    • RuntimeActionCreateRequest, RuntimeActionData, and RuntimeActionTimeoutError
  • Exported the new runtime action types/errors from the SDK entrypoints.
  • Added focused TS and Python tests for create, wait, and timeout behavior.
  • Added a minor changeset for veto-sdk and @veto/python-release.

Why

The platform runtime API is now the canonical SDK release valve for the iOS approval wallet. Agents need a first-class client path to create a pending runtime action and block until the iOS biometric approval flow resolves it.

Validation

  • PYTHONPATH=packages/sdk-python /opt/homebrew/bin/python3.11 -m pytest packages/sdk-python/tests/test_cloud_client.py -q → 3 passed
  • pnpm --filter veto-sdk exec vitest run tests/cloud/client.test.ts → 17 passed
  • pnpm --filter veto-sdk exec eslint src/cloud/client.ts src/cloud/types.ts src/index.ts tests/cloud/client.test.ts
  • /opt/homebrew/bin/python3.11 -m ruff check packages/sdk-python/veto/cloud/client.py packages/sdk-python/veto/cloud/types.py packages/sdk-python/veto/cloud/__init__.py packages/sdk-python/veto/__init__.py packages/sdk-python/tests/test_cloud_client.py
  • pnpm --filter veto-sdk exec tsc --noEmit -p tsconfig.json
  • pnpm --filter veto-sdk build
  • Live API smoke, unauthenticated: https://api.veto.so/health returns 200 and POST /v1/runtime/actions returns 401 invalid_api_key, proving the deployed route is present and protected.

Not covered here

A real production create/wait/resolve E2E requires a project-scoped VETO_API_KEY and an available iOS approval device. No VETO_API_KEY is present in the current environment.

@github-actions

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions Bot added area:sdk Changes in the TypeScript SDK area:python Changes in the Python SDK area:docs Documentation updates labels Jun 18, 2026
@yazcaleb yazcaleb changed the title [codex] Add runtime action SDK clients feat: add runtime action SDK clients Jun 18, 2026
@yazcaleb
yazcaleb marked this pull request as ready for review June 18, 2026 07:23
@yazcaleb
yazcaleb requested a review from anirudhp26 as a code owner June 18, 2026 07:23
@yazcaleb
yazcaleb enabled auto-merge (squash) June 18, 2026 07:23

@capy-ai capy-ai Bot 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.

Added 2 comments

throw new RuntimeActionTimeoutError(actionId, timeout, lastAction);
}

const waitMs = Math.max(1_000, Math.min(maxServerWaitMs, remainingTime));

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.

[🟡 Medium] [🔵 Bug]

waitRuntimeAction computes remainingTime correctly, but then forces waitMs to at least 1000, which can exceed the remaining deadline. Because fetchWithTimeout uses this.config.timeout (default 30s), a final wait request can run well past the user-specified options.timeout before RuntimeActionTimeoutError is thrown. Compute wait duration from remaining deadline (or timeout immediately when the remaining budget is below the minimum server wait) so the method honors its timeout contract.

// packages/sdk/src/cloud/client.ts
const remainingTime = deadline - Date.now();
if (remainingTime <= 0) {
  throw new RuntimeActionTimeoutError(actionId, timeout, lastAction);
}

const waitMs = Math.max(1_000, Math.min(maxServerWaitMs, remainingTime));

if client_timeout_seconds > 1.5
else client_timeout_seconds,
)
timeout_ms = max(1_000, int(server_wait_seconds * 1000))

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.

[🟡 Medium] [🔵 Bug]

wait_runtime_action derives timeout_ms from client session timeout each loop and never clamps it to the remaining opts.timeout budget. If the remaining deadline is short, it can still issue a long wait request and only raise RuntimeActionTimeoutError after that request returns, violating caller timeout expectations. Recompute timeout_ms from remaining deadline on each iteration (or fail immediately when remaining time is below the minimum wait) to keep wait behavior bounded by options.timeout.

# packages/sdk-python/veto/cloud/client.py
client_timeout_seconds = self._config.timeout / 1000
server_wait_seconds = min(
    30.0,
    client_timeout_seconds - 0.5
    if client_timeout_seconds > 1.5
    else client_timeout_seconds,
)
timeout_ms = max(1_000, int(server_wait_seconds * 1000))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:docs Documentation updates area:python Changes in the Python SDK area:sdk Changes in the TypeScript SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant