Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25,090 changes: 18,288 additions & 6,802 deletions specs/platform-openapi.json

Large diffs are not rendered by default.

30 changes: 27 additions & 3 deletions src/archastro/platform/auth.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License.
# This file is auto-generated by @archastro/sdk-generator. Do not edit.
# Content hash: 21861652201d
# Content hash: 753c8a0332f7

from __future__ import annotations

Expand DownExpand Up@@ -146,6 +146,7 @@ async def register(
full_name: str | None = None,
invite_code: str | None = None,
password: str | None = None,
set_org: str | None = None,
team_invite: str | None = None,
timezone: str | None = None,
) -> AuthTokens:
Expand All@@ -168,6 +169,7 @@ async def register(
full_name: Full name for the new account.
invite_code: Invite code for invite-gated registration. Applied only in the standard registration path.
password: Password for the new account. Required for standard (non-team-invite) registration.
set_org: Create or reuse an organization from the work-email domain and stamp the new user into it.
team_invite: Team invite ID. When provided, the user is added to the team on registration.
timezone: IANA timezone name for the new account, e.g. `"America/New_York"`.

Expand All@@ -184,6 +186,8 @@ async def register(
body["invite_code"] = invite_code
if password is not None:
body["password"] = password
if set_org is not None:
body["set_org"] = set_org
if team_invite is not None:
body["team_invite"] = team_invite
if timezone is not None:
Expand All@@ -206,6 +210,7 @@ async def request_register_magic_link(
email: str | None = None,
full_name: str | None = None,
redirect_uri: str | None = None,
set_org: str | None = None,
timezone: str | None = None,
) -> dict:
"""
Expand All@@ -224,6 +229,7 @@ async def request_register_magic_link(
email: Email address to send the registration magic link to.
full_name: Full name for the new account.
redirect_uri: URL the user is redirected to after clicking the registration link. The token is appended as a query parameter.
set_org: Create or reuse an organization from the work-email domain during confirmation.
timezone: IANA timezone name for the new account, e.g. `"America/New_York"`.

Returns:
Expand All@@ -238,6 +244,8 @@ async def request_register_magic_link(
body["full_name"] = full_name
if redirect_uri is not None:
body["redirect_uri"] = redirect_uri
if set_org is not None:
body["set_org"] = set_org
if timezone is not None:
body["timezone"] = timezone

Expand All@@ -249,7 +257,7 @@ async def request_register_magic_link(
return data

async def request_magic_link(
self, email: str | None = None, redirect_uri: str | None = None
self, email: str | None = None, redirect_uri: str | None = None, set_org: str | None = None
) -> dict:
"""
Request a magic link for login or registration
Expand All@@ -265,6 +273,7 @@ async def request_magic_link(
Args:
email: Email address to send the magic link to.
redirect_uri: URL the user is redirected to after clicking the magic link. Must be registered with the app.
set_org: For a new user, create or reuse an organization from the work-email domain during confirmation.

Returns:
No content
Expand All@@ -274,6 +283,8 @@ async def request_magic_link(
body["email"] = email
if redirect_uri is not None:
body["redirect_uri"] = redirect_uri
if set_org is not None:
body["set_org"] = set_org

data = await self._http.request(
"/api/v1/auth/request/link",
Expand DownExpand Up@@ -482,6 +493,7 @@ def register(
full_name: str | None = None,
invite_code: str | None = None,
password: str | None = None,
set_org: str | None = None,
team_invite: str | None = None,
timezone: str | None = None,
) -> AuthTokens:
Expand All@@ -504,6 +516,7 @@ def register(
full_name: Full name for the new account.
invite_code: Invite code for invite-gated registration. Applied only in the standard registration path.
password: Password for the new account. Required for standard (non-team-invite) registration.
set_org: Create or reuse an organization from the work-email domain and stamp the new user into it.
team_invite: Team invite ID. When provided, the user is added to the team on registration.
timezone: IANA timezone name for the new account, e.g. `"America/New_York"`.

Expand All@@ -520,6 +533,8 @@ def register(
body["invite_code"] = invite_code
if password is not None:
body["password"] = password
if set_org is not None:
body["set_org"] = set_org
if team_invite is not None:
body["team_invite"] = team_invite
if timezone is not None:
Expand All@@ -542,6 +557,7 @@ def request_register_magic_link(
email: str | None = None,
full_name: str | None = None,
redirect_uri: str | None = None,
set_org: str | None = None,
timezone: str | None = None,
) -> dict:
"""
Expand All@@ -560,6 +576,7 @@ def request_register_magic_link(
email: Email address to send the registration magic link to.
full_name: Full name for the new account.
redirect_uri: URL the user is redirected to after clicking the registration link. The token is appended as a query parameter.
set_org: Create or reuse an organization from the work-email domain during confirmation.
timezone: IANA timezone name for the new account, e.g. `"America/New_York"`.

Returns:
Expand All@@ -574,6 +591,8 @@ def request_register_magic_link(
body["full_name"] = full_name
if redirect_uri is not None:
body["redirect_uri"] = redirect_uri
if set_org is not None:
body["set_org"] = set_org
if timezone is not None:
body["timezone"] = timezone

Expand All@@ -584,7 +603,9 @@ def request_register_magic_link(
)
return data

def request_magic_link(self, email: str | None = None, redirect_uri: str | None = None) -> dict:
def request_magic_link(
self, email: str | None = None, redirect_uri: str | None = None, set_org: str | None = None
) -> dict:
"""
Request a magic link for login or registration
Sends a passwordless magic link to the given email address. If an account with that
Expand All@@ -599,6 +620,7 @@ def request_magic_link(self, email: str | None = None, redirect_uri: str | None
Args:
email: Email address to send the magic link to.
redirect_uri: URL the user is redirected to after clicking the magic link. Must be registered with the app.
set_org: For a new user, create or reuse an organization from the work-email domain during confirmation.

Returns:
No content
Expand All@@ -608,6 +630,8 @@ def request_magic_link(self, email: str | None = None, redirect_uri: str | None
body["email"] = email
if redirect_uri is not None:
body["redirect_uri"] = redirect_uri
if set_org is not None:
body["set_org"] = set_org

data = self._http.request(
"/api/v1/auth/request/link",
Expand Down
36 changes: 21 additions & 15 deletions src/archastro/platform/channels/api_chat_channel.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License.
# This file is auto-generated by @archastro/sdk-generator. Do not edit.
# Content hash: 47683c10bd61
# Content hash: 45505bffc4df

from collections.abc import Callable
from datetime import datetime
Expand DownExpand Up@@ -223,19 +223,19 @@ class MessageAddedPayloadMessageAttachmentsItem(TypedDict, total=False):
image_width: int | None
"Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise."
media_type: str | None
'The media category, e.g. `"video"` or `"audio"`. Present on `media` type only. `null` otherwise.'
'The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.'
name: str | None
"Display name of the media item. Present on `media` type only. `null` otherwise."
object: dict[str, Any] | None
"The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. `null` on other types."
"The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types."
title: str | None
"Display title. The page title for `scraped_link`, the artifact name for `artifact`, and the task title for `task` types. `null` on other types."
type: Required[str]
'The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.'
url: str | None
"URL to access the resource. A signed download URL for `file` and `artifact` types; the original URL for `scraped_link`; a media playback URL for `media`. `null` on `task` and `action` types."
variants: list[MessageAddedPayloadMessageAttachmentsItemVariantsItem] | None
"Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only. `null` otherwise."
"Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only; omitted otherwise."
version: int | None
"Version number of the attached artifact at the time of attachment. Present on `artifact` type only. `null` otherwise."
width: int | None
Expand DownExpand Up@@ -266,7 +266,7 @@ class MessageAddedPayloadMessage(TypedDict, total=False):
"ID of the thread that was branched from this message (`thr_...`). `null` if this message has not spawned a branch thread."
content: str | None
"Text content of the message. `null` for messages that contain only attachments."
created_at: datetime | None
created_at: str | None
"When the message was posted (ISO 8601)."
has_replies: bool | None
"Whether this message has at least one reply. Only present when explicitly requested or computed by the server."
Expand DownExpand Up@@ -303,10 +303,10 @@ class MessageAddedPayloadMessage(TypedDict, total=False):
team: str | None
"ID of the team this message is scoped to (`tem_...`). `null` if the message is not team-scoped."
thread: str | None
"ID of the thread this message belongs to (`thr_...`). `null` for messages not yet associated with a thread."
"ID of the thread this message belongs to (`thr_...`)."
type: str | None
"Optional client-defined classification for the message (for example `note` or `status`). Free-form string up to 64 characters. The value `system` is reserved for platform-authored messages and cannot be set by clients. `null` when unset."
user: str | None
user: str | dict[str, Any] | None
"The human user who sent this message. Returns a public ID string (`usr_...`) when the association is not preloaded, or an expanded user object when it is. `null` for messages sent by agents."
visibility: Literal["default", "private"] | None
"Message-level visibility. `default` is visible to anyone who can see the parent thread. `private` is restricted to the sender and explicit ACL `read` grantees."
Expand DownExpand Up@@ -463,19 +463,19 @@ class MessageUpdatedPayloadMessageAttachmentsItem(TypedDict, total=False):
image_width: int | None
"Width in pixels of the scraped preview image. Present on `scraped_link` type only. `null` otherwise."
media_type: str | None
'The media category, e.g. `"video"` or `"audio"`. Present on `media` type only. `null` otherwise.'
'The media category, e.g. `"video"` or `"audio"`. Present on `media` type only; omitted otherwise.'
name: str | None
"Display name of the media item. Present on `media` type only. `null` otherwise."
object: dict[str, Any] | None
"The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. `null` on other types."
"The full embedded object payload. For `task` type, contains the task record. For `action` type, contains the action definition. For `chart` type, contains the chart with its inline `spec`. Omitted on other types."
title: str | None
"Display title. The page title for `scraped_link`, the artifact name for `artifact`, and the task title for `task` types. `null` on other types."
type: Required[str]
'The attachment type. One of `"file"`, `"scraped_link"`, `"artifact"`, `"task"`, `"media"`, `"action"`, or `"chart"`. Determines which additional fields are present.'
url: str | None
"URL to access the resource. A signed download URL for `file` and `artifact` types; the original URL for `scraped_link`; a media playback URL for `media`. `null` on `task` and `action` types."
variants: list[MessageUpdatedPayloadMessageAttachmentsItemVariantsItem] | None
"Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only. `null` otherwise."
"Array of available encoding variants for the media item (e.g. different resolutions). Present on `media` type only; omitted otherwise."
version: int | None
"Version number of the attached artifact at the time of attachment. Present on `artifact` type only. `null` otherwise."
width: int | None
Expand DownExpand Up@@ -506,7 +506,7 @@ class MessageUpdatedPayloadMessage(TypedDict, total=False):
"ID of the thread that was branched from this message (`thr_...`). `null` if this message has not spawned a branch thread."
content: str | None
"Text content of the message. `null` for messages that contain only attachments."
created_at: datetime | None
created_at: str | None
"When the message was posted (ISO 8601)."
has_replies: bool | None
"Whether this message has at least one reply. Only present when explicitly requested or computed by the server."
Expand DownExpand Up@@ -543,10 +543,10 @@ class MessageUpdatedPayloadMessage(TypedDict, total=False):
team: str | None
"ID of the team this message is scoped to (`tem_...`). `null` if the message is not team-scoped."
thread: str | None
"ID of the thread this message belongs to (`thr_...`). `null` for messages not yet associated with a thread."
"ID of the thread this message belongs to (`thr_...`)."
type: str | None
"Optional client-defined classification for the message (for example `note` or `status`). Free-form string up to 64 characters. The value `system` is reserved for platform-authored messages and cannot be set by clients. `null` when unset."
user: str | None
user: str | dict[str, Any] | None
"The human user who sent this message. Returns a public ID string (`usr_...`) when the association is not preloaded, or an expanded user object when it is. `null` for messages sent by agents."
visibility: Literal["default", "private"] | None
"Message-level visibility. `default` is visible to anyone who can see the parent thread. `private` is restricted to the sender and explicit ACL `read` grantees."
Expand DownExpand Up@@ -715,12 +715,12 @@ async def join_team_transient(
join_response = await channel.join(payload)
return cls(channel, join_response)

# Join a user-scoped thread by ID
# Join a user-scoped thread by ID, optionally supplying local tools for a personal thread
@staticmethod
def topic_user_thread(thread_id: str) -> str:
return f"api:chat:user:thread:{thread_id}"

# Join a user-scoped thread by ID
# Join a user-scoped thread by ID, optionally supplying local tools for a personal thread
@classmethod
async def join_user_thread(
cls,
Expand All@@ -731,6 +731,8 @@ async def join_user_thread(
before_cursor: str | None = None,
include_metadata: bool | None = None,
limit: int | None = None,
local_tool_provider_id: str | None = None,
local_tools: list[dict[str, Any]] | None = None,
) -> "ApiChatChannel":
topic = cls.topic_user_thread(thread_id)
channel = socket.channel(topic)
Expand All@@ -743,6 +745,10 @@ async def join_user_thread(
payload["include_metadata"] = include_metadata
if limit is not None:
payload["limit"] = limit
if local_tool_provider_id is not None:
payload["local_tool_provider_id"] = local_tool_provider_id
if local_tools is not None:
payload["local_tools"] = local_tools
join_response = await channel.join(payload)
return cls(channel, join_response)

Expand Down
10 changes: 9 additions & 1 deletion src/archastro/platform/channels/api_tasks_channel.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License.
# This file is auto-generated by @archastro/sdk-generator. Do not edit.
# Content hash: 4b37f88c4cc7
# Content hash: 426450fa3df6

from collections.abc import Callable
from datetime import datetime
Expand DownExpand Up@@ -98,6 +98,8 @@ class TasksUpdatedPayloadTasksItem(TypedDict, total=False):
"Long-form description or notes for the task. `null` if no description has been provided."
due_date: datetime | None
"Date and time by which the task should be completed (ISO 8601). `null` if no due date is set."
epic: str | None
"Free-form grouping label. `null` when the task is not in an epic."
id: Required[str]
"Task ID (`tsk_...`)."
is_blocked: bool | None
Expand All@@ -122,6 +124,12 @@ class TasksUpdatedPayloadTasksItem(TypedDict, total=False):
"Priority level of the task from `0` (highest) to `4` (lowest). Defaults to `2` (medium) when not explicitly set."
sandbox: str | None
"ID of the developer sandbox this task is scoped to (`dsb_...`). `null` for tasks outside a sandbox environment."
source_id: str | None
"Source object identity (for example `ArchAstro/firstlanding`). `null` when the task has no source."
source_scope: str | None
"Container of the work this task is about (for example `github.com`). `null` when the task has no source. Set together with `source_type` and `source_id`."
source_type: str | None
"Kind of source object (for example `repository`). `null` when the task has no source."
status: Required[str]
'Current status of the task. One of `"open"`, `"in_progress"`, or `"done"`.'
subtasks_count: int | None
Expand Down
6 changes: 5 additions & 1 deletion src/archastro/platform/client.py
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Copyright (c) 2026 ArchAstro Inc. Licensed under the MIT License.
# This file is auto-generated by @archastro/sdk-generator. Do not edit.
# Content hash: 7ec220a0ac4f
# Content hash: f24da3972099

from urllib.parse import urlparse, urlunparse

Expand DownExpand Up@@ -53,6 +53,8 @@ def __init__(
self.bug_reports = self.v1.bug_reports
self.config = self.v1.config
self.custom_objects = self.v1.custom_objects
self.event_subscription_deliveries = self.v1.event_subscription_deliveries
self.event_subscriptions = self.v1.event_subscriptions
self.extractions = self.v1.extractions
self.files = self.v1.files
self.installation_sources = self.v1.installation_sources
Expand DownExpand Up@@ -284,6 +286,8 @@ def __init__(
self.bug_reports = self.v1.bug_reports
self.config = self.v1.config
self.custom_objects = self.v1.custom_objects
self.event_subscription_deliveries = self.v1.event_subscription_deliveries
self.event_subscriptions = self.v1.event_subscriptions
self.extractions = self.v1.extractions
self.files = self.v1.files
self.installation_sources = self.v1.installation_sources
Expand Down
Loading