mirror of
https://github.com/openai/codex.git
synced 2026-10-20 00:18:49 +00:00
Add experimental thread prediction protocol types (#49480)
## What changed Define `thread/prediction/request` with `threadId` and `sourceTurnId`, and `thread/prediction/updated` with a `completed` result containing optional text or a `failed` result. Update generated JSON schemas, TypeScript types, and Python notification models. Route prediction notifications to their thread in the TUI and ignore them in the chat widget. The request remains unimplemented and returns a method-not-found error. GitOrigin-RevId: 09922f583d5c56f808d018121c651dcd92734515
This commit is contained in:
@@ -5474,6 +5474,67 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadPredictionResult": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"completed"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResult",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"failed"
|
||||
],
|
||||
"title": "FailedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FailedThreadPredictionResult",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ThreadPredictionUpdatedNotification": {
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/ThreadPredictionResult"
|
||||
},
|
||||
"sourceTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"result",
|
||||
"sourceTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadProjectUpdatedNotification": {
|
||||
"properties": {
|
||||
"projectId": {
|
||||
@@ -7153,6 +7214,26 @@
|
||||
"title": "Thread/goal/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/prediction/updated"
|
||||
],
|
||||
"title": "Thread/prediction/updatedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadPredictionUpdatedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/prediction/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
|
||||
+83
@@ -4839,6 +4839,26 @@
|
||||
"title": "Thread/goal/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/prediction/updated"
|
||||
],
|
||||
"title": "Thread/prediction/updatedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/ThreadPredictionUpdatedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/prediction/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -23019,6 +23039,69 @@
|
||||
"title": "ThreadNameUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadPredictionResult": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"completed"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResult",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"failed"
|
||||
],
|
||||
"title": "FailedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FailedThreadPredictionResult",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ThreadPredictionUpdatedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/v2/ThreadPredictionResult"
|
||||
},
|
||||
"sourceTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"result",
|
||||
"sourceTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadPredictionUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadProjectUpdatedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
|
||||
+83
@@ -16281,6 +16281,26 @@
|
||||
"title": "Thread/goal/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
"enum": [
|
||||
"thread/prediction/updated"
|
||||
],
|
||||
"title": "Thread/prediction/updatedNotificationMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/ThreadPredictionUpdatedNotification"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Thread/prediction/updatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"method": {
|
||||
@@ -20733,6 +20753,69 @@
|
||||
"title": "ThreadNameUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadPredictionResult": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"completed"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResult",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"failed"
|
||||
],
|
||||
"title": "FailedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FailedThreadPredictionResult",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ThreadPredictionUpdatedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/ThreadPredictionResult"
|
||||
},
|
||||
"sourceTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"result",
|
||||
"sourceTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadPredictionUpdatedNotification",
|
||||
"type": "object"
|
||||
},
|
||||
"ThreadProjectUpdatedNotification": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"ThreadPredictionResult": {
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": [
|
||||
"completed"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "CompletedThreadPredictionResult",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"failed"
|
||||
],
|
||||
"title": "FailedThreadPredictionResultType",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type"
|
||||
],
|
||||
"title": "FailedThreadPredictionResult",
|
||||
"type": "object"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"result": {
|
||||
"$ref": "#/definitions/ThreadPredictionResult"
|
||||
},
|
||||
"sourceTurnId": {
|
||||
"type": "string"
|
||||
},
|
||||
"threadId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"result",
|
||||
"sourceTurnId",
|
||||
"threadId"
|
||||
],
|
||||
"title": "ThreadPredictionUpdatedNotification",
|
||||
"type": "object"
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
File diff suppressed because one or more lines are too long
+2
-1
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type ThreadPredictionResult = { "type": "completed", text: string | null, } | { "type": "failed" };
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
// GENERATED CODE! DO NOT MODIFY BY HAND!
|
||||
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ThreadPredictionResult } from "./ThreadPredictionResult";
|
||||
|
||||
export type ThreadPredictionUpdatedNotification = { threadId: string, sourceTurnId: string, result: ThreadPredictionResult, };
|
||||
@@ -526,6 +526,8 @@ export type { ThreadMetadataGitInfoUpdateParams } from "./ThreadMetadataGitInfoU
|
||||
export type { ThreadMetadataUpdateParams } from "./ThreadMetadataUpdateParams";
|
||||
export type { ThreadMetadataUpdateResponse } from "./ThreadMetadataUpdateResponse";
|
||||
export type { ThreadNameUpdatedNotification } from "./ThreadNameUpdatedNotification";
|
||||
export type { ThreadPredictionResult } from "./ThreadPredictionResult";
|
||||
export type { ThreadPredictionUpdatedNotification } from "./ThreadPredictionUpdatedNotification";
|
||||
export type { ThreadProjectUpdatedNotification } from "./ThreadProjectUpdatedNotification";
|
||||
export type { ThreadQueueChangedNotification } from "./ThreadQueueChangedNotification";
|
||||
export type { ThreadReadParams } from "./ThreadReadParams";
|
||||
|
||||
@@ -605,6 +605,12 @@ client_request_definitions! {
|
||||
serialization: thread_id(params.thread_id),
|
||||
response: v2::ThreadSetNameResponse,
|
||||
},
|
||||
#[experimental("thread/prediction/request")]
|
||||
ThreadPredictionRequest => "thread/prediction/request" {
|
||||
params: v2::ThreadPredictionRequestParams,
|
||||
serialization: thread_id(params.thread_id),
|
||||
response: v2::ThreadPredictionRequestResponse,
|
||||
},
|
||||
ThreadGoalSet => "thread/goal/set" {
|
||||
params: v2::ThreadGoalSetParams,
|
||||
serialization: thread_id(params.thread_id),
|
||||
@@ -1927,6 +1933,8 @@ server_notification_definitions! {
|
||||
ThreadNameUpdated => "thread/name/updated" (v2::ThreadNameUpdatedNotification),
|
||||
ThreadAttachmentUpdated => "thread/attachment/updated" (v2::ThreadAttachmentUpdatedNotification),
|
||||
ThreadGoalUpdated => "thread/goal/updated" (v2::ThreadGoalUpdatedNotification),
|
||||
#[experimental("thread/prediction/updated")]
|
||||
ThreadPredictionUpdated => "thread/prediction/updated" (v2::ThreadPredictionUpdatedNotification),
|
||||
ThreadGoalCleared => "thread/goal/cleared" (v2::ThreadGoalClearedNotification),
|
||||
#[experimental("thread/queue/changed")]
|
||||
ThreadQueueChanged => "thread/queue/changed" (v2::ThreadQueueChangedNotification),
|
||||
|
||||
@@ -34,6 +34,7 @@ mod rollout;
|
||||
mod thread;
|
||||
mod thread_attachment;
|
||||
mod thread_data;
|
||||
mod thread_prediction;
|
||||
mod thread_usage;
|
||||
mod turn;
|
||||
mod user_verification;
|
||||
@@ -74,6 +75,7 @@ pub use shared::*;
|
||||
pub use thread::*;
|
||||
pub use thread_attachment::*;
|
||||
pub use thread_data::*;
|
||||
pub use thread_prediction::*;
|
||||
pub use thread_usage::*;
|
||||
pub use turn::*;
|
||||
pub use user_verification::*;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
//! App-server API types for predictions.
|
||||
|
||||
use crate::JsonSchema;
|
||||
use crate::TS;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadPredictionRequestParams {
|
||||
pub thread_id: String,
|
||||
pub source_turn_id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadPredictionRequestResponse {}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct ThreadPredictionUpdatedNotification {
|
||||
pub thread_id: String,
|
||||
pub source_turn_id: String,
|
||||
pub result: ThreadPredictionResult,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(tag = "type", rename_all = "camelCase")]
|
||||
#[ts(tag = "type", rename_all = "camelCase", export_to = "v2/")]
|
||||
pub enum ThreadPredictionResult {
|
||||
Completed { text: Option<String> },
|
||||
Failed,
|
||||
}
|
||||
@@ -11,6 +11,7 @@ use crate::current_time::app_server_time_provider;
|
||||
use crate::error_code::internal_error;
|
||||
use crate::error_code::invalid_params;
|
||||
use crate::error_code::invalid_request;
|
||||
use crate::error_code::method_not_found;
|
||||
use crate::extensions::ThreadExtensionDependencies;
|
||||
use crate::extensions::app_server_extension_event_sink;
|
||||
use crate::extensions::thread_extensions;
|
||||
@@ -1443,6 +1444,9 @@ impl MessageProcessor {
|
||||
.thread_unarchive(request_id.clone(), params)
|
||||
.await
|
||||
}
|
||||
ClientRequest::ThreadPredictionRequest { .. } => Err(method_not_found(
|
||||
"thread/prediction/request is not implemented yet",
|
||||
)),
|
||||
ClientRequest::ThreadCompactStart { params, .. } => {
|
||||
self.thread_processor
|
||||
.thread_compact_start(&request_id, params)
|
||||
|
||||
@@ -66,6 +66,7 @@ pub(crate) fn without_notification_media(notification: ServerNotification) -> Se
|
||||
| ServerNotification::ThreadNameUpdated(_)
|
||||
| ServerNotification::ThreadAttachmentUpdated(_)
|
||||
| ServerNotification::ThreadGoalUpdated(_)
|
||||
| ServerNotification::ThreadPredictionUpdated(_)
|
||||
| ServerNotification::ThreadGoalCleared(_)
|
||||
| ServerNotification::ThreadQueueChanged(_)
|
||||
| ServerNotification::ProjectChanged(_)
|
||||
|
||||
@@ -71,6 +71,9 @@ pub(super) fn server_notification_thread_target(
|
||||
ServerNotification::ThreadGoalUpdated(notification) => {
|
||||
Some(notification.thread_id.as_str())
|
||||
}
|
||||
ServerNotification::ThreadPredictionUpdated(notification) => {
|
||||
Some(notification.thread_id.as_str())
|
||||
}
|
||||
ServerNotification::ThreadGoalCleared(notification) => {
|
||||
Some(notification.thread_id.as_str())
|
||||
}
|
||||
|
||||
@@ -361,6 +361,7 @@ impl ChatWidget {
|
||||
| ServerNotification::ThreadStatusChanged(_)
|
||||
| ServerNotification::ThreadReverted(_)
|
||||
| ServerNotification::ThreadQueueChanged(_)
|
||||
| ServerNotification::ThreadPredictionUpdated(_)
|
||||
| ServerNotification::ThreadArchived(_)
|
||||
| ServerNotification::ThreadDeleted(_)
|
||||
| ServerNotification::ThreadUnarchived(_)
|
||||
|
||||
@@ -61,6 +61,7 @@ from .v2_all import ThreadDeletedNotification
|
||||
from .v2_all import ThreadGoalClearedNotification
|
||||
from .v2_all import ThreadGoalUpdatedNotification
|
||||
from .v2_all import ThreadNameUpdatedNotification
|
||||
from .v2_all import ThreadPredictionUpdatedNotification
|
||||
from .v2_all import ThreadProjectUpdatedNotification
|
||||
from .v2_all import ThreadQueueChangedNotification
|
||||
from .v2_all import ThreadRealtimeClosedNotification
|
||||
@@ -144,6 +145,7 @@ KnownNotificationPayload: TypeAlias = (
|
||||
| ThreadGoalClearedNotification
|
||||
| ThreadGoalUpdatedNotification
|
||||
| ThreadNameUpdatedNotification
|
||||
| ThreadPredictionUpdatedNotification
|
||||
| ThreadProjectUpdatedNotification
|
||||
| ThreadQueueChangedNotification
|
||||
| ThreadRealtimeClosedNotification
|
||||
@@ -230,6 +232,7 @@ NOTIFICATION_MODELS: dict[str, type[KnownNotificationPayload]] = {
|
||||
"thread/goal/cleared": ThreadGoalClearedNotification,
|
||||
"thread/goal/updated": ThreadGoalUpdatedNotification,
|
||||
"thread/name/updated": ThreadNameUpdatedNotification,
|
||||
"thread/prediction/updated": ThreadPredictionUpdatedNotification,
|
||||
"thread/project/updated": ThreadProjectUpdatedNotification,
|
||||
"thread/queue/changed": ThreadQueueChangedNotification,
|
||||
"thread/realtime/closed": ThreadRealtimeClosedNotification,
|
||||
|
||||
@@ -5613,6 +5613,39 @@ class ThreadNameUpdatedNotification(BaseModel):
|
||||
thread_name: Annotated[str | None, Field(alias="threadName")] = None
|
||||
|
||||
|
||||
class CompletedThreadPredictionResult(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
text: str | None = None
|
||||
type: Annotated[Literal["completed"], Field(title="CompletedThreadPredictionResultType")]
|
||||
|
||||
|
||||
class FailedThreadPredictionResult(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
type: Annotated[Literal["failed"], Field(title="FailedThreadPredictionResultType")]
|
||||
|
||||
|
||||
class ThreadPredictionResult(
|
||||
RootModel[CompletedThreadPredictionResult | FailedThreadPredictionResult]
|
||||
):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
root: CompletedThreadPredictionResult | FailedThreadPredictionResult
|
||||
|
||||
|
||||
class ThreadPredictionUpdatedNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
result: ThreadPredictionResult
|
||||
source_turn_id: Annotated[str, Field(alias="sourceTurnId")]
|
||||
thread_id: Annotated[str, Field(alias="threadId")]
|
||||
|
||||
|
||||
class ThreadProjectUpdatedNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -9178,6 +9211,24 @@ class ThreadAttachmentUpdatedServerNotification(BaseModel):
|
||||
params: ThreadAttachmentUpdatedNotification
|
||||
|
||||
|
||||
class ThreadPredictionUpdatedServerNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
emitted_at_ms: Annotated[
|
||||
int | None,
|
||||
Field(
|
||||
alias="emittedAtMs",
|
||||
description="Unix timestamp (in milliseconds) when app-server emitted this notification.",
|
||||
),
|
||||
] = None
|
||||
method: Annotated[
|
||||
Literal["thread/prediction/updated"],
|
||||
Field(title="Thread/prediction/updatedNotificationMethod"),
|
||||
]
|
||||
params: ThreadPredictionUpdatedNotification
|
||||
|
||||
|
||||
class ThreadGoalClearedServerNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -12859,6 +12910,7 @@ class ServerNotification(
|
||||
| ThreadNameUpdatedServerNotification
|
||||
| ThreadAttachmentUpdatedServerNotification
|
||||
| ThreadGoalUpdatedServerNotification
|
||||
| ThreadPredictionUpdatedServerNotification
|
||||
| ThreadGoalClearedServerNotification
|
||||
| ThreadQueueChangedServerNotification
|
||||
| ProjectChangedServerNotification
|
||||
@@ -12948,6 +13000,7 @@ class ServerNotification(
|
||||
| ThreadNameUpdatedServerNotification
|
||||
| ThreadAttachmentUpdatedServerNotification
|
||||
| ThreadGoalUpdatedServerNotification
|
||||
| ThreadPredictionUpdatedServerNotification
|
||||
| ThreadGoalClearedServerNotification
|
||||
| ThreadQueueChangedServerNotification
|
||||
| ProjectChangedServerNotification
|
||||
|
||||
Reference in New Issue
Block a user