From 0532221c3de5427570a6f4754b7688e945e06398 Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Thu, 24 Sep 2026 18:43:57 +0000 Subject: [PATCH 1/2] ## Python SDK Changes: * `open_router.interns.get_intern_daemon_access()`: **Added** --- .speakeasy/gen.lock | 72 +++-- .speakeasy/gen.yaml | 2 +- .speakeasy/out.openapi.yaml | 131 +++++++++ .speakeasy/workflow.lock | 10 +- RELEASES.md | 12 +- docs/components/interndaemonaccess.mdx | 13 + .../getinterndaemonaccessglobals.mdx | 11 + .../getinterndaemonaccessrequest.mdx | 12 + docs/sdks/interns/README.mdx | 48 ++++ pyproject.toml | 2 +- src/openrouter/_version.py | 4 +- src/openrouter/components/__init__.py | 5 + .../components/interndaemonaccess.py | 20 ++ src/openrouter/interns.py | 256 ++++++++++++++++++ src/openrouter/operations/__init__.py | 14 + .../operations/getinterndaemonaccess.py | 146 ++++++++++ uv.lock | 2 +- 17 files changed, 730 insertions(+), 30 deletions(-) create mode 100644 docs/components/interndaemonaccess.mdx create mode 100644 docs/operations/getinterndaemonaccessglobals.mdx create mode 100644 docs/operations/getinterndaemonaccessrequest.mdx create mode 100644 src/openrouter/components/interndaemonaccess.py create mode 100644 src/openrouter/operations/getinterndaemonaccess.py diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index a3e7a8b5..f11b6c79 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,19 +1,19 @@ lockVersion: 2.0.0 id: c48cf606-fb42-4a45-9c23-8f0555307828 management: - docChecksum: d2b87b75740c953a8d17ca0730888708 + docChecksum: df3ca46aca5d14666fd33de83747f801 docVersion: 1.0.0 speakeasyVersion: 1.787.0 generationVersion: 2.914.0 - releaseVersion: 1.2.23 - configChecksum: cf04b07f1113c9a5bdb836d9750c6595 + releaseVersion: 1.2.24 + configChecksum: d02772c9403da27f5eb41cff25d529b1 repoURL: https://github.com/OpenRouterTeam/python-sdk.git installationURL: https://github.com/OpenRouterTeam/python-sdk.git published: true persistentEdits: - generation_id: 0ce8b7d7-40a6-4545-8c99-e46d21cddf64 - pristine_commit_hash: f8b73026182269af46b0f4ea8eb9bce793b0deb8 - pristine_tree_hash: 713fb275f7f68923b8b4a91d5655c233e3ab64b1 + generation_id: 54a3574d-1558-40f7-874c-16f1ae802ac5 + pristine_commit_hash: 4789f649ebdd3f148d33513703a94b992d93c522 + pristine_tree_hash: 862a783b0199eeb5d4508209f14851bb4e81dc28 features: python: acceptHeaders: 3.0.0 @@ -3105,6 +3105,10 @@ trackedFiles: id: b314b250af70 last_write_checksum: sha1:22c9aaa210f59e0d4845a03a268b6ba879fb4132 pristine_git_object: 4a98d72416014765c3e6b38b7b5eae9cbc8e2f34 + docs/components/interndaemonaccess.mdx: + id: ba56f69a1513 + last_write_checksum: sha1:52df2833e8e8483fa67bbc680d74503dd622c7f6 + pristine_git_object: 7a564fb428ba9d8b1fb680cec407748a964e4be7 docs/components/interninvokeacceptedresponse.mdx: id: fabf6978427d last_write_checksum: sha1:2a29dff72ed9ef5438d4269be8b2c0ad2cb21569 @@ -7213,6 +7217,14 @@ trackedFiles: id: 1e6b86bd352e last_write_checksum: sha1:61e6cae3e157e329be3ea0f60ed28408f55b58da pristine_git_object: 15bebf62bb77b99ccfbb68dd33a2b38d42d12b85 + docs/operations/getinterndaemonaccessglobals.mdx: + id: 9c1de03162b5 + last_write_checksum: sha1:dcb2e8aa6726ec42bd508afca59f51c599b4f258 + pristine_git_object: 95abed7a19872a8a8ea348ff40f2dca73ea5275a + docs/operations/getinterndaemonaccessrequest.mdx: + id: d3656df0343d + last_write_checksum: sha1:14d4198519fb1fe68d97ef6aa980714875bc051e + pristine_git_object: e2035a9f0347f8403d43f00136d20fc0e4641887 docs/operations/getinternglobals.mdx: id: 9bfe3e0e8a6f last_write_checksum: sha1:7f2d43fe0f91149b2982edebe432faed9bfb3bea @@ -8175,8 +8187,8 @@ trackedFiles: pristine_git_object: 08c687694efbecf50406ae7929029d39fb121295 docs/sdks/interns/README.mdx: id: 2f8a053ffe78 - last_write_checksum: sha1:fd91c1ccaefb504e09d5f4d808a147715ecefb68 - pristine_git_object: d1c3962d632fb36093e0128ccf9216b82e366c2d + last_write_checksum: sha1:9f9c8e52546e85f026cdc14bc8b277c1058c53c1 + pristine_git_object: 19b0c71ab1981ba9e05811c239ede1a2ff09e952 docs/sdks/models/README.mdx: id: 58f1ca464e0b last_write_checksum: sha1:093dd30ebdd18b9763a6956915e0dcae4ae7d5e5 @@ -8243,8 +8255,8 @@ trackedFiles: pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544 pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:9e0f472074f415d99a56fa3306425e51f8af90b5 - pristine_git_object: 61bf730ab52f84fd8420a110eba48cd1755bcdf4 + last_write_checksum: sha1:71fd2dfd99167132206446e21915b3a14726faad + pristine_git_object: 9d14083354029769ccc4ab1da4adf94fd6dfc1eb scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54 @@ -8271,8 +8283,8 @@ trackedFiles: pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137 src/openrouter/_version.py: id: d8d15ad6c586 - last_write_checksum: sha1:6847b2055d38d2d2edf8a66e79761da1d616d0d6 - pristine_git_object: c626fe71fb4be5da8602ef0383c70340821d974d + last_write_checksum: sha1:882a6f542393d7fd9dc4943bf2f7a5372a57c831 + pristine_git_object: d7a17ff85772ba6c4ceff97c65e0ea6eab17e1d3 src/openrouter/alpha.py: id: 306c4d93308d last_write_checksum: sha1:30f55a360f41376ab194b9ea725fe4e001a5ae1a @@ -8315,8 +8327,8 @@ trackedFiles: pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1 src/openrouter/components/__init__.py: id: 81754e97b3f4 - last_write_checksum: sha1:289921f26fee4755c45b555fe37997efe0bd8337 - pristine_git_object: 3e788f40a00a2aaa8d49c0121034565046799ac8 + last_write_checksum: sha1:286c1a4c6b8272e410a0da94c48d29719f989186 + pristine_git_object: 7300d1852826e3c47d7a155151cc5a473e14f56e src/openrouter/components/aabenchmarkentry.py: id: e2e0f0b48c82 last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c @@ -9693,6 +9705,10 @@ trackedFiles: id: 97fab5db9a7e last_write_checksum: sha1:d7d2493ea2f82a9c1fa1f90fae5c5365e589345f pristine_git_object: a87aacc5a001412a5789caace557974ccf931928 + src/openrouter/components/interndaemonaccess.py: + id: 023a6ecdcd2d + last_write_checksum: sha1:4098660a0247c95f4bc53cf5b40b4a56747d69b3 + pristine_git_object: 3fc691dce945dcbd24ce1a3416c5706453923afa src/openrouter/components/interninvokeacceptedresponse.py: id: b33d41d36bed last_write_checksum: sha1:0237a0fa91192a250e4162f4d6c0a764a87a9fbe @@ -11239,8 +11255,8 @@ trackedFiles: pristine_git_object: 50643a126668498dd668c7cceb9f78c03d413d32 src/openrouter/interns.py: id: d18df05c5c6d - last_write_checksum: sha1:db884b41dd732eaccaf0d979fc7a0fbb68afd115 - pristine_git_object: 2cad9a030e7346e787a30d2dd1a49290f052a0f2 + last_write_checksum: sha1:cc2bfdb1b5aca9de1861b585048597c10dc05bdb + pristine_git_object: 275720d840f8f9057d67f4322b10cab58c46bee7 src/openrouter/models/__init__.py: id: ed73b93abb3f last_write_checksum: sha1:932a790ae66ccd7d7022b39c659bcf72a664ebea @@ -11267,8 +11283,8 @@ trackedFiles: pristine_git_object: 8680343bbc90107ae6413bd5686012b1fd75d665 src/openrouter/operations/__init__.py: id: 9afcea1e7161 - last_write_checksum: sha1:f27e9cc96299cea25ce64c878423d7f809c66e6a - pristine_git_object: 4aad70a40deb2081b4877d222c7ba32cf650f24a + last_write_checksum: sha1:28ec50ab4815a2064bf6c8c3916d479984fc2120 + pristine_git_object: f85216960d4161c6e49e2d3cdf4d9a39fa12d59a src/openrouter/operations/bulkaddworkspacemembers.py: id: e0ed56117619 last_write_checksum: sha1:5c44eb0d40fdece3ac084615f6c6082be4cf1d5a @@ -11493,6 +11509,10 @@ trackedFiles: id: 9169bcde1477 last_write_checksum: sha1:b0efb3c2205f580b8bad328ccca792dfa8eb18aa pristine_git_object: 137abb8f6a48c3a7a0463370d6a254d6af406cad + src/openrouter/operations/getinterndaemonaccess.py: + id: 30c4fbbddd94 + last_write_checksum: sha1:c9a4991c38d8588d2f272710f24fa430975d4fab + pristine_git_object: 6632fbbbe4e59918369b70cf2a365880f2d315d6 src/openrouter/operations/getkey.py: id: d9769da90865 last_write_checksum: sha1:0a73a314d782011063d9879302dbb7b829d759e3 @@ -15129,5 +15149,19 @@ examples: application/json: {"error": {"code": 409, "message": "That question is no longer waiting for an answer."}} "500": application/json: {"error": {"code": 409, "message": "That question is no longer waiting for an answer."}} + getInternDaemonAccess: + speakeasy-default-get-intern-daemon-access: + parameters: + path: + internId: "7c9e6679-7425-40de-944b-e07fc1f90ae7" + responses: + "200": + application/json: {"origin": "https://research-assistant-7c9e6679.or.bot", "token": "daemon_token"} + "401": + application/json: {"error": {"code": 404, "message": "Intern not found"}} + "500": + application/json: {"error": {"code": 404, "message": "Intern not found"}} examplesVersion: 1.0.2 -releaseNotes: "## Python SDK Changes:\n* `open_router.alpha.decisions.create()`: \n * `request.provider.options` **Added**\n* `open_router.chat.send()`: \n * `request.provider.options` **Added**\n* `open_router.embeddings.generate()`: \n * `request.provider.options` **Added**\n* `open_router.presets.create_presets_chat_completions()`: \n * `request.provider.options` **Added**\n* `open_router.presets.create_presets_messages()`: \n * `request.provider.options` **Added**\n* `open_router.presets.create_presets_responses()`: \n * `request.provider.options` **Added**\n* `open_router.rerank.rerank()`: \n * `request.provider.options` **Added**\n* `open_router.responses.send()`: \n * `request.provider.options` **Added**\n* `open_router.beta.responses.send()`: \n * `request.provider.options` **Added**\n* `open_router.system_one.create()`: \n * `request.provider.options` **Added**\n" +releaseNotes: | + ## Python SDK Changes: + * `open_router.interns.get_intern_daemon_access()`: **Added** diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 4cf9fd11..263fba66 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -36,7 +36,7 @@ generation: documentation: mintlify preApplyUnionDiscriminators: true python: - version: 1.2.23 + version: 1.2.24 additionalDependencies: dev: {} main: {} diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml index c91388b7..3c21daff 100644 --- a/.speakeasy/out.openapi.yaml +++ b/.speakeasy/out.openapi.yaml @@ -13228,6 +13228,22 @@ components: - 'content' - 'role' type: 'object' + InternDaemonAccess: + description: 'The intern daemon''s origin and the bearer `ori tui --host` sends to it as `ORI_DAEMON_TOKEN`.' + example: + origin: 'https://research-assistant-7c9e6679.or.bot' + token: 'daemon_token' + properties: + origin: + pattern: '^https?:\/\/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*)(?::(\d{1,5}))?$/iu' + type: 'string' + token: + pattern: '^[\w-]+$/u' + type: 'string' + required: + - 'origin' + - 'token' + type: 'object' InternInvokeAcceptedResponse: description: 'The intern admitted the prompt. The run continues on the intern.' example: @@ -37788,6 +37804,121 @@ paths: - $ref: "#/components/parameters/AppIdentifier" - $ref: "#/components/parameters/AppDisplayName" - $ref: "#/components/parameters/AppCategories" + /interns/{internId}/daemon-access: + get: + description: 'Returns the origin and daemon token that attach `ori tui --host` to one visible, running intern. The token is a credential: the response is sent with `Cache-Control: no-store`, each reveal is logged by caller and intern, and a caller may make 10 reveals per minute. The API key selects the caller, workspace and visible interns. There is no default workspace fallback. Requests on regional hostnames such as `eu.openrouter.ai` are refused. [API key](/docs/api-reference/authentication) required.' + operationId: 'getInternDaemonAccess' + parameters: + - description: 'ID of an intern visible to the authenticated API key.' + in: 'path' + name: 'internId' + required: true + schema: + description: 'ID of an intern visible to the authenticated API key.' + example: '7c9e6679-7425-40de-944b-e07fc1f90ae7' + minLength: 1 + type: 'string' + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/InternDaemonAccess' + description: 'Daemon origin and token.' + '401': + content: + application/json: + example: + error: + code: 401 + message: 'Invalid or missing API key' + schema: + $ref: '#/components/schemas/InternLifecycleError' + description: 'Missing, unknown or provisioning API key.' + '403': + content: + application/json: + example: + error: + code: 403 + message: 'Forbidden' + schema: + $ref: '#/components/schemas/InternLifecycleError' + description: 'The key owner no longer has access, or the request used a regional hostname.' + '404': + content: + application/json: + example: + error: + code: 404 + message: 'Intern not found' + metadata: + reason: 'not_found' + retryable: false + schema: + $ref: '#/components/schemas/InternLifecycleError' + description: 'The caller is outside the Intern API programme, the intern is hidden, or lifecycle writes are disabled.' + '408': + content: + application/json: + example: + error: + code: 408 + message: 'Operation timed out after 10s. Please try again later.' + metadata: + reason: 'timeout' + retryable: true + schema: + $ref: '#/components/schemas/InternLifecycleError' + description: 'The request exceeded its route deadline. The deadline quoted in the message is the route''s own, so it differs between operations.' + '409': + content: + application/json: + example: + error: + code: 409 + message: 'This intern is not running.' + metadata: + reason: 'intern_not_running' + retryable: false + schema: + $ref: '#/components/schemas/InternLifecycleError' + description: 'The intern cannot be attached to. `metadata.reason` is `intern_not_running`, `intern_unreachable` when it has no usable address yet, or `intern_needs_restart` when it was provisioned before daemon access was available.' + '429': + content: + application/json: + example: + error: + code: 429 + message: 'Too many token reveals. Please wait a moment.' + metadata: + reason: 'rate_limited' + retryable: true + schema: + $ref: '#/components/schemas/InternLifecycleError' + description: 'The caller made more than 10 reveals in the last minute. Wait for `Retry-After` seconds.' + '500': + content: + application/json: + example: + error: + code: 500 + message: 'The request could not be completed' + metadata: + reason: 'internal_error' + retryable: true + schema: + $ref: '#/components/schemas/InternLifecycleError' + description: 'The request could not be completed. `metadata.reason` says whether to try again: `internal_error` is a transient failure and carries `metadata.retryable: true`, so the same request may be sent again, while `configuration_error` carries `retryable: false` because the next attempt reads the same missing binding or unusable stored credential.' + security: + - apiKey: [] + summary: 'Get an intern''s daemon access' + tags: + - 'Interns' + parameters: + - $ref: "#/components/parameters/AppIdentifier" + - $ref: "#/components/parameters/AppDisplayName" + - $ref: "#/components/parameters/AppCategories" /interns/{internId}/invoke: post: description: "Starts a run on one of your interns and answers `202` with the `session_id` as soon as the intern accepts it. The run keeps going on the intern after the response. Nothing about its progress comes back on this request; the intern reports through its own tools, such as Slack.\n\nSend the same `session_id` later to continue the conversation, for example to hand the intern a decision on work it started. If that session already has a run going, the prompt is delivered into it and the status is `steered`. A `session_id` is accepted only from the caller it was issued to, on the same intern; any other, including sessions started from Slack or the chat endpoint, is refused with `404`.\n\nRuns started here self-drive: the intern consents to its own tool approvals, and a question it asks is answered by its own fallback. A run ends when the intern finishes it or after its execution deadline (1 hour by default).\n\nAvailable to interns programme members. Callers outside the programme receive `404` for every path under `/api/v1/interns`." diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 45d85167..0933578e 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -2,8 +2,8 @@ speakeasyVersion: 1.787.0 sources: OpenRouter API: sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:7bfd9776c2b453f33856c928176266c2fd942f4e3ffe3713b4d961cf98081908 - sourceBlobDigest: sha256:ff57d6a05c40f98ea95dbae53ed8a31c4b7c35471b19fca8099220909e837776 + sourceRevisionDigest: sha256:02e1b7dd73a10f12b18a7600dc7a48ffdc3f4fcf79945fb84cf82561b114f3fa + sourceBlobDigest: sha256:0843485e905beb46e95e5c85e6181dd887ffe03c3e90ae46b2e8c2960413b4ff tags: - latest - 1.0.0 @@ -11,10 +11,10 @@ targets: open-router: source: OpenRouter API sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:7bfd9776c2b453f33856c928176266c2fd942f4e3ffe3713b4d961cf98081908 - sourceBlobDigest: sha256:ff57d6a05c40f98ea95dbae53ed8a31c4b7c35471b19fca8099220909e837776 + sourceRevisionDigest: sha256:02e1b7dd73a10f12b18a7600dc7a48ffdc3f4fcf79945fb84cf82561b114f3fa + sourceBlobDigest: sha256:0843485e905beb46e95e5c85e6181dd887ffe03c3e90ae46b2e8c2960413b4ff codeSamplesNamespace: open-router-python-code-samples - codeSamplesRevisionDigest: sha256:62f17d989e71d95e6e3ab18552f0dfe8006c837eb98fac27d5cc9b02760ecde9 + codeSamplesRevisionDigest: sha256:dca481e6032b170115375eac63b653a98f2e8bf08ccf70be38125d31cf96c0d8 workflow: workflowVersion: 1.0.0 speakeasyVersion: 1.787.0 diff --git a/RELEASES.md b/RELEASES.md index af38f9f5..83f7a490 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -2639,4 +2639,14 @@ Based on: ### Generated - [python v1.2.23] . ### Releases -- [PyPI v1.2.23] https://pypi.org/project/openrouter/1.2.23 - . \ No newline at end of file +- [PyPI v1.2.23] https://pypi.org/project/openrouter/1.2.23 - . + +## 2026-09-24 18:41:29 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.2.24] . +### Releases +- [PyPI v1.2.24] https://pypi.org/project/openrouter/1.2.24 - . \ No newline at end of file diff --git a/docs/components/interndaemonaccess.mdx b/docs/components/interndaemonaccess.mdx new file mode 100644 index 00000000..7a564fb4 --- /dev/null +++ b/docs/components/interndaemonaccess.mdx @@ -0,0 +1,13 @@ +--- +title: "InternDaemonAccess" +--- + +The intern daemon's origin and the bearer `ori tui --host` sends to it as `ORI_DAEMON_TOKEN`. + + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `origin` | *str* | :heavy_check_mark: | N/A | +| `token` | *str* | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/operations/getinterndaemonaccessglobals.mdx b/docs/operations/getinterndaemonaccessglobals.mdx new file mode 100644 index 00000000..95abed7a --- /dev/null +++ b/docs/operations/getinterndaemonaccessglobals.mdx @@ -0,0 +1,11 @@ +--- +title: "GetInternDaemonAccessGlobals" +--- + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| +| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| +| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| \ No newline at end of file diff --git a/docs/operations/getinterndaemonaccessrequest.mdx b/docs/operations/getinterndaemonaccessrequest.mdx new file mode 100644 index 00000000..e2035a9f --- /dev/null +++ b/docs/operations/getinterndaemonaccessrequest.mdx @@ -0,0 +1,12 @@ +--- +title: "GetInternDaemonAccessRequest" +--- + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| | +| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| | +| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| | +| `intern_id` | *str* | :heavy_check_mark: | ID of an intern visible to the authenticated API key. | 7c9e6679-7425-40de-944b-e07fc1f90ae7 | \ No newline at end of file diff --git a/docs/sdks/interns/README.mdx b/docs/sdks/interns/README.mdx index d1c3962d..19b0c71a 100644 --- a/docs/sdks/interns/README.mdx +++ b/docs/sdks/interns/README.mdx @@ -14,6 +14,7 @@ Create, inspect, update, provision, suspend and delete OpenRouter interns throug * [delete_intern](#delete_intern) - Delete an intern * [get_intern](#get_intern) - Get an intern * [update_intern](#update_intern) - Update an intern +* [get_intern_daemon_access](#get_intern_daemon_access) - Get an intern's daemon access * [provision_intern](#provision_intern) - Provision an intern * [suspend_intern](#suspend_intern) - Suspend an intern * [chat](#chat) - Stream a chat completion with an intern @@ -268,6 +269,53 @@ with OpenRouter( | errors.InternLifecycleError | 500 | application/json | | errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* | +## get_intern_daemon_access + +Returns the origin and daemon token that attach `ori tui --host` to one visible, running intern. The token is a credential: the response is sent with `Cache-Control: no-store`, each reveal is logged by caller and intern, and a caller may make 10 reveals per minute. The API key selects the caller, workspace and visible interns. There is no default workspace fallback. Requests on regional hostnames such as `eu.openrouter.ai` are refused. [API key](/docs/api-reference/authentication) required. + +### Example Usage + +```python +from openrouter import OpenRouter +import os + + +with OpenRouter( + http_referer="", + x_open_router_title="", + x_open_router_categories="", + api_key=os.getenv("OPENROUTER_API_KEY", ""), +) as open_router: + + res = open_router.interns.get_intern_daemon_access(intern_id="7c9e6679-7425-40de-944b-e07fc1f90ae7") + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `intern_id` | *str* | :heavy_check_mark: | ID of an intern visible to the authenticated API key. | 7c9e6679-7425-40de-944b-e07fc1f90ae7 | +| `http_referer` | *Optional[str]* | :heavy_minus_sign: | The app identifier should be your app's URL and is used as the primary identifier for rankings.
This is used to track API usage per application.
| | +| `x_open_router_title` | *Optional[str]* | :heavy_minus_sign: | The app display name allows you to customize how your app appears in OpenRouter's dashboard.
| | +| `x_open_router_categories` | *Optional[str]* | :heavy_minus_sign: | Comma-separated list of app categories (e.g. "cli-agent,cloud-agent"). Used for marketplace rankings.
| | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.mdx) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | | + +### Response + +**[components.InternDaemonAccess](../../components/interndaemonaccess.mdx)** + +### Errors + +| Error Type | Status Code | Content Type | +| ----------------------------- | ----------------------------- | ----------------------------- | +| errors.InternLifecycleError | 401, 403, 404, 408, 409, 429 | application/json | +| errors.InternLifecycleError | 500 | application/json | +| errors.OpenRouterDefaultError | 4XX, 5XX | \*/\* | + ## provision_intern Starts the first boot, or resumes an intern after suspension. This operation takes no request body. A body carrying any field is refused with 400 rather than ignored. The API key selects the caller, workspace and visible interns. There is no default workspace fallback. Requests on regional hostnames such as `eu.openrouter.ai` are refused. [API key](/docs/api-reference/authentication) required. diff --git a/pyproject.toml b/pyproject.toml index 61bf730a..9d140833 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openrouter" -version = "1.2.23" +version = "1.2.24" description = "Official Python Client SDK for OpenRouter." authors = [{ name = "OpenRouter" },] readme = "README-PYPI.md" diff --git a/src/openrouter/_version.py b/src/openrouter/_version.py index c626fe71..d7a17ff8 100644 --- a/src/openrouter/_version.py +++ b/src/openrouter/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "openrouter" -__version__: str = "1.2.23" +__version__: str = "1.2.24" __openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.914.0" -__user_agent__: str = "speakeasy-sdk/python 1.2.23 2.914.0 1.0.0 openrouter" +__user_agent__: str = "speakeasy-sdk/python 1.2.24 2.914.0 1.0.0 openrouter" try: if __package__ is not None: diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py index 3e788f40..7300d185 100644 --- a/src/openrouter/components/__init__.py +++ b/src/openrouter/components/__init__.py @@ -1706,6 +1706,7 @@ InternChatUserMessageRole, InternChatUserMessageTypedDict, ) + from .interndaemonaccess import InternDaemonAccess, InternDaemonAccessTypedDict from .interninvokeacceptedresponse import ( InternInvokeAcceptedResponse, InternInvokeAcceptedResponseStatus, @@ -4724,6 +4725,8 @@ "InternChatUserMessage", "InternChatUserMessageRole", "InternChatUserMessageTypedDict", + "InternDaemonAccess", + "InternDaemonAccessTypedDict", "InternInvokeAcceptedResponse", "InternInvokeAcceptedResponseStatus", "InternInvokeAcceptedResponseTypedDict", @@ -7275,6 +7278,8 @@ "InternChatUserMessage": ".internchatusermessage", "InternChatUserMessageRole": ".internchatusermessage", "InternChatUserMessageTypedDict": ".internchatusermessage", + "InternDaemonAccess": ".interndaemonaccess", + "InternDaemonAccessTypedDict": ".interndaemonaccess", "InternInvokeAcceptedResponse": ".interninvokeacceptedresponse", "InternInvokeAcceptedResponseStatus": ".interninvokeacceptedresponse", "InternInvokeAcceptedResponseTypedDict": ".interninvokeacceptedresponse", diff --git a/src/openrouter/components/interndaemonaccess.py b/src/openrouter/components/interndaemonaccess.py new file mode 100644 index 00000000..3fc691dc --- /dev/null +++ b/src/openrouter/components/interndaemonaccess.py @@ -0,0 +1,20 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from openrouter.types import BaseModel +from typing_extensions import TypedDict + + +class InternDaemonAccessTypedDict(TypedDict): + r"""The intern daemon's origin and the bearer `ori tui --host` sends to it as `ORI_DAEMON_TOKEN`.""" + + origin: str + token: str + + +class InternDaemonAccess(BaseModel): + r"""The intern daemon's origin and the bearer `ori tui --host` sends to it as `ORI_DAEMON_TOKEN`.""" + + origin: str + + token: str diff --git a/src/openrouter/interns.py b/src/openrouter/interns.py index 2cad9a03..275720d8 100644 --- a/src/openrouter/interns.py +++ b/src/openrouter/interns.py @@ -1448,6 +1448,262 @@ async def update_intern_async( raise errors.OpenRouterDefaultError("Unexpected response received", http_res) + def get_intern_daemon_access( + self, + *, + intern_id: str, + http_referer: Optional[str] = None, + x_open_router_title: Optional[str] = None, + x_open_router_categories: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> components.InternDaemonAccess: + r"""Get an intern's daemon access + + Returns the origin and daemon token that attach `ori tui --host` to one visible, running intern. The token is a credential: the response is sent with `Cache-Control: no-store`, each reveal is logged by caller and intern, and a caller may make 10 reveals per minute. The API key selects the caller, workspace and visible interns. There is no default workspace fallback. Requests on regional hostnames such as `eu.openrouter.ai` are refused. [API key](/docs/api-reference/authentication) required. + + If set, this operation will use `api_key` from the global security. + + :param intern_id: ID of an intern visible to the authenticated API key. + :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings. + This is used to track API usage per application. + + :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = operations.GetInternDaemonAccessRequest( + http_referer=http_referer, + x_open_router_title=x_open_router_title, + x_open_router_categories=x_open_router_categories, + intern_id=intern_id, + ) + + req = self._build_request( + method="GET", + path="/interns/{internId}/daemon-access", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + _globals=operations.GetInternDaemonAccessGlobals( + http_referer=self.sdk_configuration.globals.http_referer, + x_open_router_title=self.sdk_configuration.globals.x_open_router_title, + x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + allowed_fields=["api_key"], + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["5XX"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="getInternDaemonAccess", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, components.Security + ), + tags=["Interns"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(components.InternDaemonAccess, http_res) + if utils.match_response( + http_res, ["401", "403", "404", "408", "409", "429"], "application/json" + ): + response_data = unmarshal_json_response( + errors.InternLifecycleErrorData, http_res + ) + raise errors.InternLifecycleError(response_data, http_res) + if utils.match_response(http_res, "500", "application/json"): + response_data = unmarshal_json_response( + errors.InternLifecycleErrorData, http_res + ) + raise errors.InternLifecycleError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.OpenRouterDefaultError("Unexpected response received", http_res) + + async def get_intern_daemon_access_async( + self, + *, + intern_id: str, + http_referer: Optional[str] = None, + x_open_router_title: Optional[str] = None, + x_open_router_categories: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> components.InternDaemonAccess: + r"""Get an intern's daemon access + + Returns the origin and daemon token that attach `ori tui --host` to one visible, running intern. The token is a credential: the response is sent with `Cache-Control: no-store`, each reveal is logged by caller and intern, and a caller may make 10 reveals per minute. The API key selects the caller, workspace and visible interns. There is no default workspace fallback. Requests on regional hostnames such as `eu.openrouter.ai` are refused. [API key](/docs/api-reference/authentication) required. + + If set, this operation will use `api_key` from the global security. + + :param intern_id: ID of an intern visible to the authenticated API key. + :param http_referer: The app identifier should be your app's URL and is used as the primary identifier for rankings. + This is used to track API usage per application. + + :param x_open_router_title: The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + :param x_open_router_categories: Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = operations.GetInternDaemonAccessRequest( + http_referer=http_referer, + x_open_router_title=x_open_router_title, + x_open_router_categories=x_open_router_categories, + intern_id=intern_id, + ) + + req = self._build_request_async( + method="GET", + path="/interns/{internId}/daemon-access", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + _globals=operations.GetInternDaemonAccessGlobals( + http_referer=self.sdk_configuration.globals.http_referer, + x_open_router_title=self.sdk_configuration.globals.x_open_router_title, + x_open_router_categories=self.sdk_configuration.globals.x_open_router_categories, + ), + security=self.sdk_configuration.security, + allow_empty_value=None, + allowed_fields=["api_key"], + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + else: + retries = utils.RetryConfig( + "backoff", utils.BackoffStrategy(500, 60000, 1.5, 3600000), True + ) + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["5XX"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="getInternDaemonAccess", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, components.Security + ), + tags=["Interns"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(components.InternDaemonAccess, http_res) + if utils.match_response( + http_res, ["401", "403", "404", "408", "409", "429"], "application/json" + ): + response_data = unmarshal_json_response( + errors.InternLifecycleErrorData, http_res + ) + raise errors.InternLifecycleError(response_data, http_res) + if utils.match_response(http_res, "500", "application/json"): + response_data = unmarshal_json_response( + errors.InternLifecycleErrorData, http_res + ) + raise errors.InternLifecycleError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.OpenRouterDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.OpenRouterDefaultError("Unexpected response received", http_res) + def provision_intern( self, *, diff --git a/src/openrouter/operations/__init__.py b/src/openrouter/operations/__init__.py index 4aad70a4..f8521696 100644 --- a/src/openrouter/operations/__init__.py +++ b/src/openrouter/operations/__init__.py @@ -469,6 +469,12 @@ GetInternRequest, GetInternRequestTypedDict, ) + from .getinterndaemonaccess import ( + GetInternDaemonAccessGlobals, + GetInternDaemonAccessGlobalsTypedDict, + GetInternDaemonAccessRequest, + GetInternDaemonAccessRequestTypedDict, + ) from .getkey import ( GetKeyData, GetKeyDataTypedDict, @@ -1319,6 +1325,10 @@ "GetGuardrailGlobalsTypedDict", "GetGuardrailRequest", "GetGuardrailRequestTypedDict", + "GetInternDaemonAccessGlobals", + "GetInternDaemonAccessGlobalsTypedDict", + "GetInternDaemonAccessRequest", + "GetInternDaemonAccessRequestTypedDict", "GetInternGlobals", "GetInternGlobalsTypedDict", "GetInternRequest", @@ -2088,6 +2098,10 @@ "GetInternGlobalsTypedDict": ".getintern", "GetInternRequest": ".getintern", "GetInternRequestTypedDict": ".getintern", + "GetInternDaemonAccessGlobals": ".getinterndaemonaccess", + "GetInternDaemonAccessGlobalsTypedDict": ".getinterndaemonaccess", + "GetInternDaemonAccessRequest": ".getinterndaemonaccess", + "GetInternDaemonAccessRequestTypedDict": ".getinterndaemonaccess", "GetKeyData": ".getkey", "GetKeyDataTypedDict": ".getkey", "GetKeyGlobals": ".getkey", diff --git a/src/openrouter/operations/getinterndaemonaccess.py b/src/openrouter/operations/getinterndaemonaccess.py new file mode 100644 index 00000000..6632fbbb --- /dev/null +++ b/src/openrouter/operations/getinterndaemonaccess.py @@ -0,0 +1,146 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from openrouter.types import BaseModel, UNSET_SENTINEL +from openrouter.utils import FieldMetadata, HeaderMetadata, PathParamMetadata +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class GetInternDaemonAccessGlobalsTypedDict(TypedDict): + http_referer: NotRequired[str] + r"""The app identifier should be your app's URL and is used as the primary identifier for rankings. + This is used to track API usage per application. + + """ + x_open_router_title: NotRequired[str] + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + x_open_router_categories: NotRequired[str] + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + +class GetInternDaemonAccessGlobals(BaseModel): + http_referer: Annotated[ + Optional[str], + pydantic.Field(alias="HTTP-Referer"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The app identifier should be your app's URL and is used as the primary identifier for rankings. + This is used to track API usage per application. + + """ + + x_open_router_title: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Title"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + + x_open_router_categories: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Categories"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class GetInternDaemonAccessRequestTypedDict(TypedDict): + intern_id: str + r"""ID of an intern visible to the authenticated API key.""" + http_referer: NotRequired[str] + r"""The app identifier should be your app's URL and is used as the primary identifier for rankings. + This is used to track API usage per application. + + """ + x_open_router_title: NotRequired[str] + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + x_open_router_categories: NotRequired[str] + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + +class GetInternDaemonAccessRequest(BaseModel): + intern_id: Annotated[ + str, + pydantic.Field(alias="internId"), + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] + r"""ID of an intern visible to the authenticated API key.""" + + http_referer: Annotated[ + Optional[str], + pydantic.Field(alias="HTTP-Referer"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The app identifier should be your app's URL and is used as the primary identifier for rankings. + This is used to track API usage per application. + + """ + + x_open_router_title: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Title"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The app display name allows you to customize how your app appears in OpenRouter's dashboard. + + """ + + x_open_router_categories: Annotated[ + Optional[str], + pydantic.Field(alias="X-OpenRouter-Categories"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""Comma-separated list of app categories (e.g. \"cli-agent,cloud-agent\"). Used for marketplace rankings. + + """ + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + ["HTTP-Referer", "X-OpenRouter-Title", "X-OpenRouter-Categories"] + ) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m diff --git a/uv.lock b/uv.lock index 15b23cdc..50d434fd 100644 --- a/uv.lock +++ b/uv.lock @@ -213,7 +213,7 @@ wheels = [ [[package]] name = "openrouter" -version = "1.2.23" +version = "1.2.24" source = { editable = "." } dependencies = [ { name = "httpcore" }, From 7e3d19a0d6137735a601df8aaa59a8427336fae3 Mon Sep 17 00:00:00 2001 From: "speakeasy-github[bot]" <128539517+speakeasy-github[bot]@users.noreply.github.com> Date: Thu, 24 Sep 2026 18:44:06 +0000 Subject: [PATCH 2/2] empty commit to trigger [run-tests] workflow