mirror of
https://github.com/openai/codex.git
synced 2026-11-05 20:10:33 +00:00
feat(app-server): expose usage report
This commit is contained in:
@@ -4092,6 +4092,24 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageRange": {
|
||||
"enum": [
|
||||
"day",
|
||||
"week"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageReadParams": {
|
||||
"properties": {
|
||||
"range": {
|
||||
"$ref": "#/definitions/UsageRange"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"range"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
@@ -4891,6 +4909,30 @@
|
||||
"title": "Plugin/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"usage/read"
|
||||
],
|
||||
"title": "Usage/readRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/UsageReadParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Usage/readRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
|
||||
+195
@@ -829,6 +829,30 @@
|
||||
"title": "Plugin/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/v2/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"usage/read"
|
||||
],
|
||||
"title": "Usage/readRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/v2/UsageReadParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Usage/readRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -18601,6 +18625,177 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageContributorKind": {
|
||||
"enum": [
|
||||
"skill",
|
||||
"subagent",
|
||||
"agentTask",
|
||||
"app",
|
||||
"mcpServer",
|
||||
"plugin"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageEntry": {
|
||||
"properties": {
|
||||
"attributedTokens": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"$ref": "#/definitions/v2/UsageContributorKind"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"percentOfUsage": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attributedTokens",
|
||||
"id",
|
||||
"kind",
|
||||
"label",
|
||||
"percentOfUsage"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageHeadline": {
|
||||
"properties": {
|
||||
"entry": {
|
||||
"$ref": "#/definitions/v2/UsageEntry"
|
||||
},
|
||||
"note": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entry"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageRange": {
|
||||
"enum": [
|
||||
"day",
|
||||
"week"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageReadParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"range": {
|
||||
"$ref": "#/definitions/v2/UsageRange"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"range"
|
||||
],
|
||||
"title": "UsageReadParams",
|
||||
"type": "object"
|
||||
},
|
||||
"UsageReadResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"report": {
|
||||
"$ref": "#/definitions/v2/UsageReport"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"report"
|
||||
],
|
||||
"title": "UsageReadResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"UsageReport": {
|
||||
"properties": {
|
||||
"agentTasks": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"apps": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"generatedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"headline": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/v2/UsageHeadline"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mcpServers": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"range": {
|
||||
"$ref": "#/definitions/v2/UsageRange"
|
||||
},
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"subagents": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/v2/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"totalTokens": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"trackedFrom": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"agentTasks",
|
||||
"apps",
|
||||
"generatedAt",
|
||||
"mcpServers",
|
||||
"plugins",
|
||||
"range",
|
||||
"skills",
|
||||
"subagents",
|
||||
"totalTokens"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
+195
@@ -1577,6 +1577,30 @@
|
||||
"title": "Plugin/listRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
"$ref": "#/definitions/RequestId"
|
||||
},
|
||||
"method": {
|
||||
"enum": [
|
||||
"usage/read"
|
||||
],
|
||||
"title": "Usage/readRequestMethod",
|
||||
"type": "string"
|
||||
},
|
||||
"params": {
|
||||
"$ref": "#/definitions/UsageReadParams"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"method",
|
||||
"params"
|
||||
],
|
||||
"title": "Usage/readRequest",
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"id": {
|
||||
@@ -16425,6 +16449,177 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageContributorKind": {
|
||||
"enum": [
|
||||
"skill",
|
||||
"subagent",
|
||||
"agentTask",
|
||||
"app",
|
||||
"mcpServer",
|
||||
"plugin"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageEntry": {
|
||||
"properties": {
|
||||
"attributedTokens": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"$ref": "#/definitions/UsageContributorKind"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"percentOfUsage": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attributedTokens",
|
||||
"id",
|
||||
"kind",
|
||||
"label",
|
||||
"percentOfUsage"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageHeadline": {
|
||||
"properties": {
|
||||
"entry": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"note": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entry"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageRange": {
|
||||
"enum": [
|
||||
"day",
|
||||
"week"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageReadParams": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"range": {
|
||||
"$ref": "#/definitions/UsageRange"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"range"
|
||||
],
|
||||
"title": "UsageReadParams",
|
||||
"type": "object"
|
||||
},
|
||||
"UsageReadResponse": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"properties": {
|
||||
"report": {
|
||||
"$ref": "#/definitions/UsageReport"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"report"
|
||||
],
|
||||
"title": "UsageReadResponse",
|
||||
"type": "object"
|
||||
},
|
||||
"UsageReport": {
|
||||
"properties": {
|
||||
"agentTasks": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"apps": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"generatedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"headline": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/UsageHeadline"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mcpServers": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"range": {
|
||||
"$ref": "#/definitions/UsageRange"
|
||||
},
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"subagents": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"totalTokens": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"trackedFrom": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"agentTasks",
|
||||
"apps",
|
||||
"generatedAt",
|
||||
"mcpServers",
|
||||
"plugins",
|
||||
"range",
|
||||
"skills",
|
||||
"subagents",
|
||||
"totalTokens"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UserInput": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"UsageRange": {
|
||||
"enum": [
|
||||
"day",
|
||||
"week"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"range": {
|
||||
"$ref": "#/definitions/UsageRange"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"range"
|
||||
],
|
||||
"title": "UsageReadParams",
|
||||
"type": "object"
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"definitions": {
|
||||
"UsageContributorKind": {
|
||||
"enum": [
|
||||
"skill",
|
||||
"subagent",
|
||||
"agentTask",
|
||||
"app",
|
||||
"mcpServer",
|
||||
"plugin"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageEntry": {
|
||||
"properties": {
|
||||
"attributedTokens": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"$ref": "#/definitions/UsageContributorKind"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
"percentOfUsage": {
|
||||
"format": "uint8",
|
||||
"minimum": 0.0,
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"attributedTokens",
|
||||
"id",
|
||||
"kind",
|
||||
"label",
|
||||
"percentOfUsage"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageHeadline": {
|
||||
"properties": {
|
||||
"entry": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"note": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"entry"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UsageRange": {
|
||||
"enum": [
|
||||
"day",
|
||||
"week"
|
||||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UsageReport": {
|
||||
"properties": {
|
||||
"agentTasks": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"apps": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"generatedAt": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"headline": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/UsageHeadline"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"mcpServers": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"plugins": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"range": {
|
||||
"$ref": "#/definitions/UsageRange"
|
||||
},
|
||||
"skills": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"subagents": {
|
||||
"items": {
|
||||
"$ref": "#/definitions/UsageEntry"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"totalTokens": {
|
||||
"format": "int64",
|
||||
"type": "integer"
|
||||
},
|
||||
"trackedFrom": {
|
||||
"format": "int64",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"agentTasks",
|
||||
"apps",
|
||||
"generatedAt",
|
||||
"mcpServers",
|
||||
"plugins",
|
||||
"range",
|
||||
"skills",
|
||||
"subagents",
|
||||
"totalTokens"
|
||||
],
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"report": {
|
||||
"$ref": "#/definitions/UsageReport"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"report"
|
||||
],
|
||||
"title": "UsageReadResponse",
|
||||
"type": "object"
|
||||
}
|
||||
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 UsageContributorKind = "skill" | "subagent" | "agentTask" | "app" | "mcpServer" | "plugin";
|
||||
@@ -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 { UsageContributorKind } from "./UsageContributorKind";
|
||||
|
||||
export type UsageEntry = { kind: UsageContributorKind, id: string, label: string, attributedTokens: number, percentOfUsage: number, };
|
||||
@@ -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 { UsageEntry } from "./UsageEntry";
|
||||
|
||||
export type UsageHeadline = { entry: UsageEntry, note: string | null, };
|
||||
@@ -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 UsageRange = "day" | "week";
|
||||
@@ -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 { UsageRange } from "./UsageRange";
|
||||
|
||||
export type UsageReadParams = { range: UsageRange, };
|
||||
@@ -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 { UsageReport } from "./UsageReport";
|
||||
|
||||
export type UsageReadResponse = { report: UsageReport, };
|
||||
@@ -0,0 +1,8 @@
|
||||
// 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 { UsageEntry } from "./UsageEntry";
|
||||
import type { UsageHeadline } from "./UsageHeadline";
|
||||
import type { UsageRange } from "./UsageRange";
|
||||
|
||||
export type UsageReport = { range: UsageRange, generatedAt: number, trackedFrom: number | null, totalTokens: number, headline: UsageHeadline | null, skills: Array<UsageEntry>, subagents: Array<UsageEntry>, agentTasks: Array<UsageEntry>, apps: Array<UsageEntry>, mcpServers: Array<UsageEntry>, plugins: Array<UsageEntry>, };
|
||||
@@ -452,6 +452,13 @@ export type { TurnStatus } from "./TurnStatus";
|
||||
export type { TurnSteerParams } from "./TurnSteerParams";
|
||||
export type { TurnSteerResponse } from "./TurnSteerResponse";
|
||||
export type { TurnsPage } from "./TurnsPage";
|
||||
export type { UsageContributorKind } from "./UsageContributorKind";
|
||||
export type { UsageEntry } from "./UsageEntry";
|
||||
export type { UsageHeadline } from "./UsageHeadline";
|
||||
export type { UsageRange } from "./UsageRange";
|
||||
export type { UsageReadParams } from "./UsageReadParams";
|
||||
export type { UsageReadResponse } from "./UsageReadResponse";
|
||||
export type { UsageReport } from "./UsageReport";
|
||||
export type { UserInput } from "./UserInput";
|
||||
export type { WarningNotification } from "./WarningNotification";
|
||||
export type { WebSearchAction } from "./WebSearchAction";
|
||||
|
||||
@@ -635,6 +635,11 @@ client_request_definitions! {
|
||||
serialization: None,
|
||||
response: v2::PluginListResponse,
|
||||
},
|
||||
UsageRead => "usage/read" {
|
||||
params: v2::UsageReadParams,
|
||||
serialization: None,
|
||||
response: v2::UsageReadResponse,
|
||||
},
|
||||
PluginInstalled => "plugin/installed" {
|
||||
params: v2::PluginInstalledParams,
|
||||
serialization: None,
|
||||
|
||||
@@ -24,6 +24,7 @@ mod review;
|
||||
mod thread;
|
||||
mod thread_data;
|
||||
mod turn;
|
||||
mod usage;
|
||||
mod windows_sandbox;
|
||||
|
||||
pub use account::*;
|
||||
@@ -51,6 +52,7 @@ pub use shared::*;
|
||||
pub use thread::*;
|
||||
pub use thread_data::*;
|
||||
pub use turn::*;
|
||||
pub use usage::*;
|
||||
pub use windows_sandbox::*;
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
use codex_protocol::protocol::UsageContributorKind as CoreUsageContributorKind;
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use ts_rs::TS;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase", export_to = "v2/")]
|
||||
pub enum UsageRange {
|
||||
Day,
|
||||
Week,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct UsageReadParams {
|
||||
pub range: UsageRange,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct UsageEntry {
|
||||
pub kind: UsageContributorKind,
|
||||
pub id: String,
|
||||
pub label: String,
|
||||
#[ts(type = "number")]
|
||||
pub attributed_tokens: i64,
|
||||
pub percent_of_usage: u8,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct UsageHeadline {
|
||||
pub entry: UsageEntry,
|
||||
pub note: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct UsageReport {
|
||||
pub range: UsageRange,
|
||||
#[ts(type = "number")]
|
||||
pub generated_at: i64,
|
||||
#[ts(type = "number | null")]
|
||||
pub tracked_from: Option<i64>,
|
||||
#[ts(type = "number")]
|
||||
pub total_tokens: i64,
|
||||
pub headline: Option<UsageHeadline>,
|
||||
pub skills: Vec<UsageEntry>,
|
||||
pub subagents: Vec<UsageEntry>,
|
||||
pub agent_tasks: Vec<UsageEntry>,
|
||||
pub apps: Vec<UsageEntry>,
|
||||
pub mcp_servers: Vec<UsageEntry>,
|
||||
pub plugins: Vec<UsageEntry>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct UsageReadResponse {
|
||||
pub report: UsageReport,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(rename_all = "camelCase", export_to = "v2/")]
|
||||
pub enum UsageContributorKind {
|
||||
Skill,
|
||||
Subagent,
|
||||
AgentTask,
|
||||
App,
|
||||
McpServer,
|
||||
Plugin,
|
||||
}
|
||||
|
||||
impl From<CoreUsageContributorKind> for UsageContributorKind {
|
||||
fn from(value: CoreUsageContributorKind) -> Self {
|
||||
match value {
|
||||
CoreUsageContributorKind::Skill => Self::Skill,
|
||||
CoreUsageContributorKind::Subagent => Self::Subagent,
|
||||
CoreUsageContributorKind::AgentTask => Self::AgentTask,
|
||||
CoreUsageContributorKind::App => Self::App,
|
||||
CoreUsageContributorKind::McpServer => Self::McpServer,
|
||||
CoreUsageContributorKind::Plugin => Self::Plugin,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,6 +206,7 @@ Example with notification opt-out:
|
||||
- `plugin/skill/read` — read remote plugin skill markdown on demand by `remoteMarketplaceName`, `remotePluginId`, and `skillName`. This lets clients preview uninstalled remote plugin skills without downloading the plugin bundle.
|
||||
- `skills/changed` — notification emitted when watched local skill files change.
|
||||
- `app/list` — list available apps.
|
||||
- `usage/read` — read forward-only local token usage for a rolling `day` or `week` range, grouped by skills, subagents, agent tasks, apps, MCP servers, and plugins when Codex has tracked those contributors in sqlite.
|
||||
- `remoteControl/enable` — experimental; enable remote control for the current app-server process and return the current remote-control status snapshot. The caller is responsible for persisting the desired setting outside app-server.
|
||||
- `remoteControl/disable` — experimental; disable remote control for the current app-server process and return the current remote-control status snapshot. This does not revoke already enrolled controller devices.
|
||||
- `remoteControl/status/read` — experimental; read the current remote-control status snapshot. `status` is one of `disabled`, `connecting`, `connected`, or `errored`; `serverName` is the local machine name used by this app-server process; `environmentId` is a string when the app-server has a current enrollment and `null` when that enrollment is cleared, invalidated, or remote control is disabled.
|
||||
|
||||
@@ -36,6 +36,7 @@ use crate::request_processors::SearchRequestProcessor;
|
||||
use crate::request_processors::ThreadGoalRequestProcessor;
|
||||
use crate::request_processors::ThreadRequestProcessor;
|
||||
use crate::request_processors::TurnRequestProcessor;
|
||||
use crate::request_processors::UsageRequestProcessor;
|
||||
use crate::request_processors::WindowsSandboxRequestProcessor;
|
||||
use crate::request_serialization::QueuedInitializedRequest;
|
||||
use crate::request_serialization::RequestSerializationQueueKey;
|
||||
@@ -182,6 +183,7 @@ pub(crate) struct MessageProcessor {
|
||||
thread_goal_processor: ThreadGoalRequestProcessor,
|
||||
thread_processor: ThreadRequestProcessor,
|
||||
turn_processor: TurnRequestProcessor,
|
||||
usage_processor: UsageRequestProcessor,
|
||||
windows_sandbox_processor: WindowsSandboxRequestProcessor,
|
||||
request_serialization_queues: RequestSerializationQueues,
|
||||
}
|
||||
@@ -428,9 +430,10 @@ impl MessageProcessor {
|
||||
thread_watch_manager.clone(),
|
||||
Arc::clone(&thread_list_state_permit),
|
||||
thread_goal_processor.clone(),
|
||||
state_db,
|
||||
state_db.clone(),
|
||||
Arc::clone(&skills_watcher),
|
||||
);
|
||||
let usage_processor = UsageRequestProcessor::new(state_db);
|
||||
let turn_processor = TurnRequestProcessor::new(
|
||||
auth_manager.clone(),
|
||||
Arc::clone(&thread_manager),
|
||||
@@ -507,6 +510,7 @@ impl MessageProcessor {
|
||||
thread_goal_processor,
|
||||
thread_processor,
|
||||
turn_processor,
|
||||
usage_processor,
|
||||
windows_sandbox_processor,
|
||||
request_serialization_queues: RequestSerializationQueues::default(),
|
||||
}
|
||||
@@ -1123,6 +1127,11 @@ impl MessageProcessor {
|
||||
ClientRequest::PluginList { params, .. } => {
|
||||
self.plugin_processor.plugin_list(params).await
|
||||
}
|
||||
ClientRequest::UsageRead { params, .. } => self
|
||||
.usage_processor
|
||||
.usage_read(params)
|
||||
.await
|
||||
.map(|response| Some(response.into())),
|
||||
ClientRequest::PluginInstalled { params, .. } => {
|
||||
self.plugin_processor.plugin_installed(params).await
|
||||
}
|
||||
|
||||
@@ -474,6 +474,7 @@ mod search;
|
||||
mod thread_processor;
|
||||
mod token_usage_replay;
|
||||
mod turn_processor;
|
||||
mod usage_processor;
|
||||
mod windows_sandbox_processor;
|
||||
|
||||
pub(crate) use account_processor::AccountRequestProcessor;
|
||||
@@ -496,6 +497,7 @@ pub(crate) use search::SearchRequestProcessor;
|
||||
pub(crate) use thread_goal_processor::ThreadGoalRequestProcessor;
|
||||
pub(crate) use thread_processor::ThreadRequestProcessor;
|
||||
pub(crate) use turn_processor::TurnRequestProcessor;
|
||||
pub(crate) use usage_processor::UsageRequestProcessor;
|
||||
pub(crate) use windows_sandbox_processor::WindowsSandboxRequestProcessor;
|
||||
|
||||
use crate::error_code::internal_error;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
use super::*;
|
||||
use crate::error_code::internal_error;
|
||||
use chrono::Utc;
|
||||
use codex_app_server_protocol::UsageEntry;
|
||||
use codex_app_server_protocol::UsageHeadline;
|
||||
use codex_app_server_protocol::UsageRange;
|
||||
use codex_app_server_protocol::UsageReadParams;
|
||||
use codex_app_server_protocol::UsageReadResponse;
|
||||
use codex_app_server_protocol::UsageReport;
|
||||
use codex_rollout::StateDbHandle;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct UsageRequestProcessor {
|
||||
state_db: Option<StateDbHandle>,
|
||||
}
|
||||
|
||||
impl UsageRequestProcessor {
|
||||
pub(crate) fn new(state_db: Option<StateDbHandle>) -> Self {
|
||||
Self { state_db }
|
||||
}
|
||||
|
||||
pub(crate) async fn usage_read(
|
||||
&self,
|
||||
params: UsageReadParams,
|
||||
) -> Result<UsageReadResponse, JSONRPCErrorError> {
|
||||
let state_db = self
|
||||
.state_db
|
||||
.as_ref()
|
||||
.ok_or_else(|| internal_error("sqlite state db unavailable for usage"))?;
|
||||
let report = state_db
|
||||
.read_usage_report(state_usage_range(params.range), Utc::now().timestamp())
|
||||
.await
|
||||
.map_err(|err| internal_error(format!("failed to read usage report: {err}")))?;
|
||||
Ok(UsageReadResponse {
|
||||
report: UsageReport {
|
||||
range: api_usage_range(report.range),
|
||||
generated_at: report.generated_at,
|
||||
tracked_from: report.tracked_from,
|
||||
total_tokens: report.total_tokens,
|
||||
headline: report.headline.map(|headline| UsageHeadline {
|
||||
entry: usage_entry(headline.entry),
|
||||
note: headline.note,
|
||||
}),
|
||||
skills: report.skills.into_iter().map(usage_entry).collect(),
|
||||
subagents: report.subagents.into_iter().map(usage_entry).collect(),
|
||||
agent_tasks: report.agent_tasks.into_iter().map(usage_entry).collect(),
|
||||
apps: report.apps.into_iter().map(usage_entry).collect(),
|
||||
mcp_servers: report.mcp_servers.into_iter().map(usage_entry).collect(),
|
||||
plugins: report.plugins.into_iter().map(usage_entry).collect(),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn usage_entry(entry: codex_state::UsageEntry) -> UsageEntry {
|
||||
UsageEntry {
|
||||
kind: entry.kind.into(),
|
||||
id: entry.id,
|
||||
label: entry.label,
|
||||
attributed_tokens: entry.attributed_tokens,
|
||||
percent_of_usage: entry.percent_of_usage,
|
||||
}
|
||||
}
|
||||
|
||||
fn state_usage_range(value: UsageRange) -> codex_state::UsageRange {
|
||||
match value {
|
||||
UsageRange::Day => codex_state::UsageRange::Day,
|
||||
UsageRange::Week => codex_state::UsageRange::Week,
|
||||
}
|
||||
}
|
||||
|
||||
fn api_usage_range(value: codex_state::UsageRange) -> UsageRange {
|
||||
match value {
|
||||
codex_state::UsageRange::Day => UsageRange::Day,
|
||||
codex_state::UsageRange::Week => UsageRange::Week,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user