Python SDK
spectre-terminal 패키지의 클라이언트, 스트림, 터미널 탐색, 오류.
설치
pip install spectre-terminalSpectre Terminal의 Local API를 위한 Python 클라이언트입니다.
from spectre_terminal import Terminal
terminal = Terminal.discover()
for connection in terminal.connections():
print(connection.id, connection.exchange, connection.market, connection.status.state)공개 인터페이스는 Terminal(HTTP: 시장 데이터, 계정,
거래 명령, 워크스페이스), Stream(WebSocket),
models의 모델, errors의 오류,
discovery의 탐색 헬퍼입니다. 패키지를 임포트해도 네트워크에는
접근하지 않습니다.
Terminal
루프백 인터페이스의 Local API를 통해 접근하는, 실행 중인 Spectre Terminal입니다.
모든 메서드는 동기이며 models의 타입이 지정된 모델을
반환합니다. 오류는 SpectreTerminalError의 하위 클래스입니다.
터미널 자체의 거부는 ApiError, 터미널이 없는 경우는
TerminalUnreachable입니다.
Args
token— Settings App → 일반 → Local API에서 복사한 토큰입니다.port— 리스너 포트입니다. 터미널이SPECTRE_LOCAL_API_PORT로 시작되지 않았다면48180이며,discover는instance.json에서 읽습니다.host—127.0.0.1또는localhost입니다. 그 외의 값은 거부됩니다.timeout— 응답을 기다리는 시간(초)입니다. 콜드 상태의 시장 작업은 터미널이 거래소에서 스트림을 여는 동안 최대 3초가 걸릴 수 있습니다.
Terminal()
Terminal(
token: str,
*,
port: int = discovery.DEFAULT_PORT,
host: str = discovery.DEFAULT_HOST,
timeout: float = 10.0,
)discover()
Terminal.discover(token: str | None = None, *, port: int | None = None) -> Terminal환경에서 클라이언트를 만들고 터미널이 API v1을 제공하는지 확인합니다.
토큰은 token 또는 SPECTRE_LOCAL_API_TOKEN입니다. 둘 다 없으면
TokenMissing이 발생합니다. 포트는 port, 없으면 터미널의
instance.json에 있는 local_api_port(discovery 참고), 그것도
없으면 48180입니다. 그다음 /v1/meta를 한 번 읽습니다. 다른 API
버전을 제공하는 터미널은 IncompatibleTerminal을 발생시키고,
더 이상 유효하지 않은 토큰이나 꺼져 있는 API는 코드 unauthorized의
ApiError를 발생시킵니다.
host
host: str클라이언트가 통신하는 루프백 호스트입니다.
port
port: int리스너 포트입니다.
base_url
base_url: strhttp://<host>:<port>/v1.
stream_url
stream_url: strws://<host>:<port>/v1/stream.
meta()
meta() -> MetaGET /v1/meta: API 버전, 빌드, 토큰의 권한, 제한, 스트림의 토픽입니다.
HTTP 작업: GET /v1/meta
health()
health() -> HealthGET /v1/health: 리스너 가동 시간과 시장 데이터 허브의 카운터입니다.
HTTP 작업: GET /v1/health
connections()
connections() -> list[Connection]GET /v1/connections: 터미널의 모든 연결입니다(connections:read).
HTTP 작업: GET /v1/connections
connection()
connection(id: int) -> ConnectionGET /v1/connections/{id}: 연결 하나입니다. 그런 id가 없으면 not_found입니다.
HTTP 작업: GET /v1/connections/{id}
instruments()
instruments(
*,
connection_id: int | None = None,
exchange: str | None = None,
market: str | None = None,
q: str | None = None,
limit: int | None = None,
cursor: str | None = None,
) -> Page[Instrument]GET /v1/instruments: 한 거래소와 마켓의 카탈로그 한 페이지입니다.
페어는 connection_id로, 또는 exchange와 market으로 지정합니다
(둘 중 하나는 필수입니다). q는 심볼이나 기준 코인의 부분 문자열로
대소문자 구분 없이 필터링합니다. limit는 1-2000(기본값 500)이고,
cursor는 이전 페이지의 next_cursor입니다.
HTTP 작업: GET /v1/instruments
iter_instruments()
iter_instruments(
*,
connection_id: int | None = None,
exchange: str | None = None,
market: str | None = None,
q: str | None = None,
limit: int | None = None,
cursor: str | None = None,
) -> Iterator[Instrument]카탈로그의 모든 종목이며, next_cursor를 따라 페이지 단위로 읽습니다.
매개변수는 instruments와 같습니다. cursor는 시작 위치입니다.
intervals()
intervals() -> IntervalsGET /v1/market/intervals: 터미널이 아는 캔들 및 클러스터 인터벌입니다.
HTTP 작업: GET /v1/market/intervals
candles()
candles(
instrument: str,
interval: str,
*,
limit: int | None = None,
end: int | None = None,
connection_id: int | None = None,
) -> CandlesGET /v1/market/candles: 창의 차트가 쓰는 경로로 읽는 봉 히스토리입니다.
interval은 intervals의 코드(1m, 5m, ...)입니다.
limit는 최대 2000(기본값 500)이고, end는 UTC 밀리초 단위의
오른쪽 경계(기본값은 현재)입니다. 거래소가 응답하지 않으면
ApiError unavailable입니다.
HTTP 작업: GET /v1/market/candles
trades()
trades(
instrument: str,
*,
limit: int | None = None,
since_ts: int | None = None,
connection_id: int | None = None,
) -> TradesGET /v1/market/trades: 종목의 최근 체결이며, 오래된 것부터 나열됩니다.
limit는 1-1000(기본값 100)입니다. since_ts는 그 UTC 밀리초보다
먼저 받은 체결을 제외합니다. 콜드 상태의 종목은 데이터를 최대 3초
기다립니다. 3초 동안 체결이 없으면 정말로 빈 목록입니다.
HTTP 작업: GET /v1/market/trades
snapshot()
snapshot(instrument: str, *, connection_id: int | None = None) -> SnapshotGET /v1/market/snapshot: 최우선 매수·매도 호가, 마지막 체결, 마크 가격, 티커입니다.
HTTP 작업: GET /v1/market/snapshot
orderbook()
orderbook(
instrument: str,
*,
depth: int | None = None,
connection_id: int | None = None,
) -> OrderBookGET /v1/market/orderbook: 호가창의 상단 depth개 레벨(1-200, 기본값 50)입니다.
3초 안에 전체 호가창이 없으면 ApiError unavailable입니다. 빈
호가창은 빈 시장처럼 보이기 때문입니다.
HTTP 작업: GET /v1/market/orderbook
clusters()
clusters(instrument: str, *, connection_id: int | None = None) -> ClustersGET /v1/market/clusters: 터미널의 인터벌로 계산된 최신 클러스터 버킷입니다.
창에 열려 있지 않은 종목은 요청 시 계산되며 히스토리는 백엔드에서
가져옵니다. 히스토리를 가져오는 데 3초 넘게 걸리면 응답은
ApiError not_active이며, 몇 초 뒤 다시 시도하면 클러스터를
받을 수 있습니다.
HTTP 작업: GET /v1/market/clusters
account_orders()
account_orders(connection_id: int) -> AccountOrdersGET /v1/account/orders: 한 연결의 미체결 주문과 트리거 주문입니다.
connection_id는 필수입니다. 계정 작업에는 기본 연결이 없습니다.
알 수 없는 id는 ApiError not_found입니다.
HTTP 작업: GET /v1/account/orders
account_positions()
account_positions(connection_id: int) -> AccountPositionsGET /v1/account/positions: 한 연결의 열린 포지션입니다.
HTTP 작업: GET /v1/account/positions
account_balances()
account_balances(connection_id: int) -> AccountBalancesGET /v1/account/balances: 통화별로 거래소가 보낸 최신 잔고입니다.
잔고는 API를 켠 시점부터 수집됩니다. 그 뒤로 아무 변동이 없는 통화는 목록에 없습니다.
HTTP 작업: GET /v1/account/balances
account_fills()
account_fills(
connection_id: int,
*,
limit: int | None = None,
since_ts: int | None = None,
) -> AccountFillsGET /v1/account/fills: 연결의 최근 체결 내역이며, 오래된 것부터 나열됩니다.
limit는 1-1000(기본값 100)입니다. since_ts는 거래소 시간이 그
UTC 밀리초 이후인 체결 내역만 남깁니다. 버퍼는 API를 켠 뒤의 최근
체결 내역 1000건입니다.
HTTP 작업: GET /v1/account/fills
place_order()
place_order(
connection_id: int,
instrument: str,
*,
side: str,
order_type: str,
price: Money | None = None,
size: Money | None = None,
notional: Money | None = None,
reduce_only: bool = False,
post_only: bool = False,
time_in_force: str | None = None,
client_key: str | None = None,
) -> AcceptedPOST /v1/orders: 창이 하는 방식 그대로 주문을 넣습니다.
side는 buy 또는 sell입니다. order_type은 limit(price
필요) 또는 market(price 없음)입니다. size(기준 코인)와
notional(호가 통화 금액) 중 정확히 하나만 지정합니다. 금액은
Decimal, str 또는 int이며 문자열로 전송됩니다. float는
거부됩니다. time_in_force는 gtc, ioc, fok 또는
post_only이며, 없으면 거래소의 기본값입니다. client_key는
멱등성 키입니다. 같은 키로 반복하면 이전 응답을 반환하고 아무것도
넣지 않습니다.
응답은 Accepted입니다. 거래소가 아니라 터미널이 접수했다는
뜻이며, 결과는 account.orders 또는 account_orders로 도착합니다.
거래할 수 없는 연결은 ApiError not_tradable, 거래소의 최솟값과
스텝에 따른 거부는 invalid_request,
limits.commands_per_second보다 빠른 요청은 rate_limited입니다.
HTTP 작업: POST /v1/orders
cancel_order()
cancel_order(connection_id: int, instrument: str, order_id: str) -> AcceptedDELETE /v1/orders/{id}: 터미널 키(t-...) 또는 거래소 id로 주문 하나를 취소합니다.
취소는 거래소로 바로 전송됩니다. 확인은 스트림으로 도착합니다.
Accepted.key는 None입니다.
HTTP 작업: DELETE /v1/orders/{id}
cancel_all()
cancel_all(connection_id: int, instrument: str) -> AcceptedPOST /v1/orders/cancel-all: 종목의 모든 주문을 취소합니다(스페이스 바).
HTTP 작업: POST /v1/orders/cancel-all
close_position()
close_position(connection_id: int, instrument: str) -> AcceptedPOST /v1/positions/close: 창이 하는 방식 그대로 종목의 포지션을 청산합니다.
선물에서는 포지션 크기만큼 close_position이 설정된 시장가 주문을
보냅니다. 현물에서는 "모두 취소하고 청산"을 하나의 원자적 명령으로
처리합니다. 열린 포지션이 없으면 ApiError invalid_request입니다.
HTTP 작업: POST /v1/positions/close
place_trigger()
place_trigger(
connection_id: int,
instrument: str,
*,
kind: str,
trigger_price: Money,
side: str | None = None,
notional: Money | None = None,
rule: str | None = None,
client_key: str | None = None,
) -> AcceptedPOST /v1/orders/trigger: 창이 넣는 것과 같은 스톱로스, 테이크프로핏 또는 스톱입니다.
kind는 stop_loss 또는 take_profit이며 열린 포지션에
걸립니다(방향, 수량, 규칙은 포지션에서 가져오며, 포지션이 없으면
ApiError invalid_request입니다). 또는 stop이며, 이때는 side
(buy/sell)와 notional(호가 통화 금액)이 필요하고 선택적으로
rule(price_above_or_equal 또는 price_below_or_equal; 없으면
매수는 시장 가격 위, 매도는 시장 가격 아래)을 받습니다. client_key는
place_order에서와 같은 멱등성 키입니다.
Accepted.key는 트리거의 키(sl_…, tp_…, stop_…)이며,
account_orders에서 트리거의 client_id로 나타납니다. 취소와
수정에는 그곳의 숫자 id를 사용합니다. 터미널에 트리거 주문이 없는
거래소는 ApiError unsupported입니다.
HTTP 작업: POST /v1/orders/trigger
cancel_trigger()
cancel_trigger(connection_id: int, instrument: str, trigger_id: int | str) -> AcceptedDELETE /v1/orders/trigger/{id}: 숫자 id로 트리거 하나를 취소합니다.
id는 account_orders에 있는 것입니다. Accepted.key는 None입니다.
HTTP 작업: DELETE /v1/orders/trigger/{id}
cancel_all_triggers()
cancel_all_triggers(connection_id: int, instrument: str) -> AcceptedPOST /v1/orders/trigger/cancel-all: 종목의 모든 트리거를 취소합니다.
일반 주문은 남습니다. 일반 주문은 cancel_all로 취소합니다.
HTTP 작업: POST /v1/orders/trigger/cancel-all
amend_trigger()
amend_trigger(
connection_id: int,
instrument: str,
trigger_id: int | str,
*,
kind: str,
trigger_price: Money,
side: str | None = None,
rule: str | None = None,
) -> AcceptedPATCH /v1/orders/trigger/{id}: 트리거를 새 가격으로 옮깁니다.
창의 순차 교체 방식입니다. 이전 트리거를 취소하고 새 트리거를
넣습니다. kind는 필수입니다(stop_loss, take_profit 또는
stop). stop에는 side도 필요하며 선택적으로 rule을 받습니다.
Accepted.key는 None입니다.
HTTP 작업: PATCH /v1/orders/trigger/{id}
leverage()
leverage(connection_id: int, instrument: str) -> LeverageGET /v1/account/leverage(account:read): 레버리지와 마진 모드입니다.
터미널의 캐시에서 읽습니다. 터미널이 아직 건드리지 않은 종목은
ApiError not_active입니다. 창에서 열거나 set_leverage를
호출하면 캐시에 들어갑니다.
HTTP 작업: GET /v1/account/leverage
set_leverage()
set_leverage(
connection_id: int,
instrument: str,
*,
leverage: int | None = None,
mode: str | None = None,
) -> AcceptedPOST /v1/account/leverage(trading:write): 창이 하는 방식 그대로 레버리지를 설정합니다.
leverage(1 이상의 정수) 또는 mode(max 또는 smart) 중
정확히 하나만 지정합니다. 응답은 key가 None인 Accepted입니다.
적용된 값은 거래소가 응답한 뒤 leverage에 나타납니다.
HTTP 작업: POST /v1/account/leverage
set_margin_mode()
set_margin_mode(connection_id: int, instrument: str, margin_mode: str) -> AcceptedPOST /v1/account/margin-mode(trading:write): cross 또는 isolated입니다.
포지션이 열려 있는 동안의 변경은 창에서와 같이 거래소가 거부합니다.
Accepted 응답은 아직 그것을 알지 못합니다.
HTTP 작업: POST /v1/account/margin-mode
workspace()
workspace() -> WorkspaceGET /v1/workspace(workspace:read): 모든 창과 그 탭, 스택, 차트입니다.
창이 구조가 바뀔 때마다 게시하는 스냅샷에서 읽으므로, 이 호출은 창을 기다리지 않습니다. 식별자는 터미널의 이번 실행에서만 쓰이는 내부 번호입니다.
HTTP 작업: GET /v1/workspace
workspace_window()
workspace_window(window_id: int) -> WindowGET /v1/workspace/windows/{id}: 창 하나입니다. 알 수 없는 id는 not_found입니다.
HTTP 작업: GET /v1/workspace/windows/{id}
open_stack()
open_stack(
instrument: str,
*,
connection_id: int | None = None,
chart: bool = False,
target: str = 'new_tab',
window_id: int | None = None,
activate: bool = True,
) -> WorkspaceOutcomePOST /v1/workspace/stacks(workspace:write): 새 탭 또는 새 창의 스택입니다.
target은 new_tab(window_id에, 없으면 포커스된 창에) 또는
new_window입니다. chart는 스택 위에 같은 종목의 차트를 엽니다.
activate=False는 탭을 백그라운드에서 엽니다. 새 창은 항상 포커스를
가져갑니다. 응답은 창, 탭, 새 위젯을 알려 줍니다. 터미널의 카탈로그에
없는 종목은 invalid_request입니다.
HTTP 작업: POST /v1/workspace/stacks
open_tab()
open_tab(
items: Sequence[TabItem | str],
*,
name: str | None = None,
target: str = 'new_tab',
window_id: int | None = None,
activate: bool = True,
) -> WorkspaceOutcomePOST /v1/workspace/tabs(workspace:write): 종목마다 열 하나씩 배치한 탭입니다.
items의 각 항목 — TabItem 또는 종목 주소 문자열 — 은 목록
순서대로 열이 됩니다. 스택 하나와, chart가 있으면 그 위의
차트입니다. 항목은 1개에서 50개까지입니다. name은 탭 이름(최대
64자)이며, 없으면 터미널이 유일한 종목 또는 첫 종목에 개수를 붙여
탭 이름을 짓습니다(BTCUSDT +1). target, window_id, activate는
open_stack에서와 같습니다. 거부 시에는 항목이 명시되며
(items[1]: …) 창에는 아무것도 전달되지 않습니다.
HTTP 작업: POST /v1/workspace/tabs
add_stacks()
add_stacks(
window_id: int,
tab_id: int,
items: Sequence[TabItem | str],
) -> WorkspaceOutcomePOST /v1/workspace/windows/{id}/tabs/{tab}/stacks: 탭의 마지막 열 뒤에 추가되는 열입니다.
items는 open_tab과 같습니다. 탭의 이름과 열 너비는 그대로
유지됩니다. 그런 창이나 탭이 없으면 not_found입니다. 응답에는
추가된 stacks와 charts만 나열됩니다.
open_multiview()
open_multiview(
base: str,
*,
target: str | None = None,
window_id: int | None = None,
activate: bool = True,
) -> WorkspaceOutcomePOST /v1/workspace/multiview(workspace:write): 모든 거래소에서 코인을 엽니다.
창의 멀티뷰 버튼과 같은 계획입니다. base는 코인(BTC) 또는
페어(BTC/USDT)입니다. target을 None으로 두면 멀티뷰의 "열기"
설정을 따릅니다. 코인에 해당하는 셀이 없으면 not_found입니다.
HTTP 작업: POST /v1/workspace/multiview
set_stack_instrument()
set_stack_instrument(
widget_id: int,
instrument: str,
*,
connection_id: int | None = None,
) -> WorkspaceOutcomePATCH /v1/workspace/stacks/{widget_id}: 스택의 그룹에서 다른 종목으로 바꿉니다.
close_stack()
close_stack(widget_id: int) -> WorkspaceOutcomeDELETE /v1/workspace/stacks/{widget_id}: 스택의 닫기 버튼과 같이 스택 하나를 닫습니다.
close_tab()
close_tab(window_id: int, tab_id: int) -> WorkspaceOutcomeDELETE /v1/workspace/windows/{id}/tabs/{tab}: 탭을 닫습니다.
창의 유일한 탭은 닫을 수 없습니다(invalid_request).
activate_tab()
activate_tab(window_id: int, tab_id: int) -> WorkspaceOutcomePOST /v1/workspace/windows/{id}/tabs/{tab}/activate: 탭을 선택합니다.
창의 포커스는 바뀌지 않습니다. activate_window를 참고하십시오.
HTTP 작업: POST /v1/workspace/windows/{id}/tabs/{tab}/activate
close_window()
close_window(window_id: int) -> WorkspaceOutcomeDELETE /v1/workspace/windows/{id}: 메인 창은 invalid_request입니다.
HTTP 작업: DELETE /v1/workspace/windows/{id}
activate_window()
activate_window(window_id: int) -> WorkspaceOutcomePOST /v1/workspace/windows/{id}/activate: 창을 복원하고 맨 앞으로 가져옵니다.
settings()
settings(
*,
scope: str | None = None,
category: str | None = None,
key: str | None = None,
connection_id: int | None = None,
instrument: str | None = None,
) -> SettingsGET /v1/settings(settings:read): 저장된 그대로의 행이며, 기본값은 채워지지 않습니다.
매개변수가 없으면 연결이 없는 전역 행입니다.
instrument는 페어의 행(범위 order_book)을,
connection_id는 연결의 행을 나열합니다. 각 행은 update_settings로
쓸 수 있는지를 writable로 알려 줍니다.
HTTP 작업: GET /v1/settings
orderbook_settings()
orderbook_settings(connection_id: int, instrument: str) -> OrderbookSettingsGET /v1/settings/orderbook(settings:read): 값이 결정된 스택 설정입니다.
창이 쓰는 단계 — 연결에 있는 페어의 행, 연결의 기본값, 연결이 없는
페어의 행, 전역 기본값 — 를 따르며, 모든 키에 resolved_from이
있습니다.
HTTP 작업: GET /v1/settings/orderbook
update_settings()
update_settings(changes: Sequence[SettingChange]) -> SettingsAppliedPATCH /v1/settings(settings:write): Settings App이 하는 방식 그대로 설정을 씁니다.
모든 변경은 먼저 터미널의 카탈로그와 대조하여 검사합니다(알 수 없는
키, 잘못된 타입, 범위 밖, 잘못된 형태 — changes[i]를 명시한
invalid_request이며 아무것도 기록되지 않습니다). 레버리지는 여기서
unsupported입니다(set_leverage를 사용합니다). 그다음 변경이
순서대로 적용됩니다. Settings App과 같은 행, 창 이벤트, 서비스
캐시입니다. 처음 실패한 변경이 목록을 멈추고 예외를 발생시킵니다.
그 앞의 변경은 적용된 채로 남습니다.
HTTP 작업: PATCH /v1/settings
stream()
stream() -> Stream/v1/stream에 연결하는 Stream이며, async with로 사용합니다.
Stream
/v1/stream에 대한 연결 하나입니다.
비동기 컨텍스트 매니저로(또는 connect / close로) 사용합니다.
subscribe와 unsubscribe는 요청을 보내고 응답을 기다리며,
async for frame in stream은
Event,
Gap,
SubscriptionError를 도착 순서대로 내놓습니다.
반복은 연결이 닫히면 끝납니다. 서버가 CLOSE_RAISES에 있는 코드로
닫으면 호출자가 알아차리도록 StreamClosed가 발생하고,
close_code / close_reason에 서버가 보낸 내용이 남습니다.
호출자가 반복하지 않는 동안 프레임은 max_pending개까지
버퍼링됩니다. 그 이상이면 클라이언트는 소켓 읽기를 멈추고, 터미널은
그것으로 클라이언트가 느리다는 것을 알게 됩니다(gap 프레임, 그다음
코드 4008로 닫음).
Args
url—ws://127.0.0.1:<port>/v1/stream이며,stream이 만들어 줍니다.token— 핸드셰이크 헤더용 bearer 토큰입니다.open_timeout— 핸드셰이크를 기다리는 시간(초)입니다.request_timeout—subscribe/unsubscribe의 응답을 기다리는 시간(초)입니다.None이면 응답이나 종료까지 기다립니다.max_pending— 이터레이터보다 앞서 버퍼링하는 프레임 수입니다.max_size— 받아들이는 최대 프레임 크기(바이트)입니다.
Stream()
Stream(
url: str,
token: str,
*,
open_timeout: float = 10.0,
request_timeout: float | None = None,
max_pending: int = 1000,
max_size: int | None = 16 * 1024 * 1024,
)url
url: str스트림 URL입니다.
connected
connected: bool핸드셰이크 성공부터 종료까지 True입니다.
close_code
close_code: int | None연결이 닫힌 뒤의 WebSocket 종료 코드이며, 그 전에는 None입니다.
close_reason
close_reason: str | None연결이 닫힌 뒤의 종료 사유이며, 그 전에는 None입니다.
connect()
async connect() -> Stream연결을 엽니다. async with가 호출하며, 이미 열려 있으면 아무것도 하지 않습니다.
close()
async close(code: int = 1000, reason: str = '') -> None연결을 닫고 서버가 종료 핸드셰이크를 마칠 때까지 기다립니다.
subscribe()
async subscribe(
topic: str,
instrument: str | None = None,
*,
connection_id: int | None = None,
**params: Any,
) -> Subscribedtopic을 구독하고 서버의 응답을 기다립니다.
topic은 /v1/meta의 topics 중 하나입니다. 시장 토픽
(trades, ticker, mark_price, book.top, clusters)에는
instrument가 필요하며, connection_id는 선택 사항으로 없으면
일반 규칙에 따라 선택됩니다. 계정 토픽(account.orders,
account.positions, account.balances, account.fills)에는
connection_id가 필요하고 종목은 받지 않습니다. 요청에 종목이
실리지 않습니다. workspace와 settings는 둘 다 받지 않습니다.
터미널당 하나이며, workspace는 현재 스냅샷을 먼저 보내고
settings는 기록된 행마다 프레임을 보냅니다. params는
book.top에만 의미가 있고(depth 1-200, interval_ms >= 50) 다른
토픽은 무시합니다. 응답은 구독 id와 연결(터미널 토픽은 None)을
알려 줍니다. error 응답은 StreamRequestError를 발생시킵니다.
unsubscribe()
async unsubscribe(sub: Subscribed | str) -> UnsubscribedSubscribed 또는 그 id로 구독을 제거합니다.
알 수 없는 구독 id에는 not_found로 응답하며
StreamRequestError가 발생합니다.
터미널 탐색
instance_path()
instance_path() -> Path이 플랫폼에서 터미널의 instance.json이 있는 경로입니다.
Linux: $XDG_DATA_HOME 또는 ~/.local/share, macOS:
~/Library/Application Support, Windows: %LOCALAPPDATA%, 그다음
%APPDATA% — 각각 뒤에 spectre-terminal/instance.json이 붙습니다.
파일이 반드시 있어야 하는 것은 아닙니다.
read_port()
read_port(path: Path | None = None) -> int | Noneinstance.json에 게시된 Local API 포트이며, 알 수 없으면 None입니다.
None은 파일이 없거나 읽을 수 없다는 뜻입니다. 이 경우 호출자는
DEFAULT_PORT로 되돌아갑니다. local_api_port가 null이거나 없는
파일은 터미널이 API를 끈 채 실행 중이라는 뜻이며, 이 경우
LocalApiDisabled가 발생합니다.
오류
SpectreTerminalError
class SpectreTerminalError(Exception)spectre_terminal이 발생시키는 모든 오류의 기본 클래스입니다.
ApiError
class ApiError(SpectreTerminalError)
ApiError(code: str, message: str, status: int)터미널이 요청에 오류 엔벨로프로 응답했습니다.
code는 계약의 안정적인 코드(unauthorized,
not_found, invalid_request, unsupported, not_active,
rate_limited, unavailable, ...)이고, message는 함께 온 사람이
읽기 위한 텍스트, status는 HTTP 상태입니다. JSON이 아닌 오류
본문은 code="unknown"이 되며 본문 텍스트가 메시지입니다.
TerminalUnreachable
class TerminalUnreachable(SpectreTerminalError)루프백 포트에서 응답한 터미널이 없습니다. 연결이 거부되었거나 시간이 초과되었습니다.
LocalApiDisabled
class LocalApiDisabled(SpectreTerminalError)instance.json에 따르면 터미널은 실행 중이지만 Local API가 꺼져 있습니다.
TokenMissing
class TokenMissing(SpectreTerminalError)토큰이 주어지지 않았고 SPECTRE_LOCAL_API_TOKEN도 설정되어 있지 않습니다.
IncompatibleTerminal
class IncompatibleTerminal(SpectreTerminalError)
IncompatibleTerminal(api_version: str, supported: str)터미널이 이 클라이언트가 지원하지 않는 API 버전을 제공합니다.
StreamRequestError
class StreamRequestError(SpectreTerminalError)
StreamRequestError(code: str, message: str)스트림이 subscribe 또는 unsubscribe 요청에 오류 프레임으로 응답했습니다.
StreamClosed
class StreamClosed(SpectreTerminalError)
StreamClosed(code: int | None, reason: str | None)서버가 호출자가 알아차려야 하는 코드로 스트림을 닫았습니다.
1001 — API가 꺼졌거나 토큰이 재발급되었습니다. 4008 — 이
클라이언트가 너무 느리게 읽었습니다. 4029 — 토큰당 연결 수
제한입니다. 1006 — 종료 프레임 없이 연결이 끊어졌습니다.
spectre-terminal 코드의 커밋 2d1c324에서 생성되었습니다.