summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-07-10 16:21:26 -0400
committerDax Raad <[email protected]>2025-07-10 16:25:38 -0400
commitc056b0add9221c32cd50452d4b9b884f2be67021 (patch)
tree70621d6f1ce337aaef5fb29b0113635c081ceef9
parentb00bb3c083712a6f107f104257339a8f36e5a189 (diff)
downloadopencode-c056b0add9221c32cd50452d4b9b884f2be67021.tar.gz
opencode-c056b0add9221c32cd50452d4b9b884f2be67021.zip
add step finish part
-rw-r--r--packages/opencode/src/session/index.ts5
-rw-r--r--packages/opencode/src/session/message-v2.ts29
-rw-r--r--packages/tui/sdk/.stats.yml4
-rw-r--r--packages/tui/sdk/session.go129
4 files changed, 149 insertions, 18 deletions
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index 6ca120512..d1744d0ab 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -721,6 +721,11 @@ export namespace Session {
const usage = getUsage(model.info, value.usage, value.providerMetadata)
next.cost += usage.cost
next.tokens = usage.tokens
+ next.parts.push({
+ type: "step-finish",
+ tokens: usage.tokens,
+ cost: usage.cost,
+ })
break
case "text-start":
diff --git a/packages/opencode/src/session/message-v2.ts b/packages/opencode/src/session/message-v2.ts
index fba34f4c0..aadc1a5e2 100644
--- a/packages/opencode/src/session/message-v2.ts
+++ b/packages/opencode/src/session/message-v2.ts
@@ -116,6 +116,25 @@ export namespace MessageV2 {
})
export type StepStartPart = z.infer<typeof StepStartPart>
+ export const StepFinishPart = z
+ .object({
+ type: z.literal("step-finish"),
+ cost: z.number(),
+ tokens: z.object({
+ input: z.number(),
+ output: z.number(),
+ reasoning: z.number(),
+ cache: z.object({
+ read: z.number(),
+ write: z.number(),
+ }),
+ }),
+ })
+ .openapi({
+ ref: "StepFinishPart",
+ })
+ export type StepFinishPart = z.infer<typeof StepFinishPart>
+
const Base = z.object({
id: z.string(),
sessionID: z.string(),
@@ -137,9 +156,11 @@ export namespace MessageV2 {
})
export type User = z.infer<typeof User>
- export const AssistantPart = z.discriminatedUnion("type", [TextPart, ToolPart, StepStartPart]).openapi({
- ref: "AssistantMessagePart",
- })
+ export const AssistantPart = z
+ .discriminatedUnion("type", [TextPart, ToolPart, StepStartPart, StepFinishPart])
+ .openapi({
+ ref: "AssistantMessagePart",
+ })
export type AssistantPart = z.infer<typeof AssistantPart>
export const Assistant = Base.extend({
@@ -164,8 +185,8 @@ export namespace MessageV2 {
cwd: z.string(),
root: z.string(),
}),
- cost: z.number(),
summary: z.boolean().optional(),
+ cost: z.number(),
tokens: z.object({
input: z.number(),
output: z.number(),
diff --git a/packages/tui/sdk/.stats.yml b/packages/tui/sdk/.stats.yml
index 225a0e490..4449c4d95 100644
--- a/packages/tui/sdk/.stats.yml
+++ b/packages/tui/sdk/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 22
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-37247433660e125f9a79ff173d8007f13192d28a40f4e599e002446a6ed0c128.yml
-openapi_spec_hash: 8095ebe2d88259381a58e7b0c87244c4
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-eb25bb3673f94d0e98a7036e2a2b0ed7ad63d1598665f2d5e091ec0835273798.yml
+openapi_spec_hash: 62f6a8a06aaa4f4ae13e85d56652724f
config_hash: 589ec6a935a43a3c49a325ece86cbda2
diff --git a/packages/tui/sdk/session.go b/packages/tui/sdk/session.go
index 1f19b97f5..6321d1ff6 100644
--- a/packages/tui/sdk/session.go
+++ b/packages/tui/sdk/session.go
@@ -438,13 +438,17 @@ func (r AssistantMessageErrorName) IsKnown() bool {
type AssistantMessagePart struct {
Type AssistantMessagePartType `json:"type,required"`
ID string `json:"id"`
+ Cost float64 `json:"cost"`
// This field can have the runtime type of [ToolPartState].
- State interface{} `json:"state"`
- Synthetic bool `json:"synthetic"`
- Text string `json:"text"`
- Tool string `json:"tool"`
- JSON assistantMessagePartJSON `json:"-"`
- union AssistantMessagePartUnion
+ State interface{} `json:"state"`
+ Synthetic bool `json:"synthetic"`
+ Text string `json:"text"`
+ // This field can have the runtime type of
+ // [AssistantMessagePartStepFinishPartTokens].
+ Tokens interface{} `json:"tokens"`
+ Tool string `json:"tool"`
+ JSON assistantMessagePartJSON `json:"-"`
+ union AssistantMessagePartUnion
}
// assistantMessagePartJSON contains the JSON metadata for the struct
@@ -452,9 +456,11 @@ type AssistantMessagePart struct {
type assistantMessagePartJSON struct {
Type apijson.Field
ID apijson.Field
+ Cost apijson.Field
State apijson.Field
Synthetic apijson.Field
Text apijson.Field
+ Tokens apijson.Field
Tool apijson.Field
raw string
ExtraFields map[string]apijson.Field
@@ -476,12 +482,14 @@ func (r *AssistantMessagePart) UnmarshalJSON(data []byte) (err error) {
// AsUnion returns a [AssistantMessagePartUnion] interface which you can cast to
// the specific types for more type safety.
//
-// Possible runtime types of the union are [TextPart], [ToolPart], [StepStartPart].
+// Possible runtime types of the union are [TextPart], [ToolPart], [StepStartPart],
+// [AssistantMessagePartStepFinishPart].
func (r AssistantMessagePart) AsUnion() AssistantMessagePartUnion {
return r.union
}
-// Union satisfied by [TextPart], [ToolPart] or [StepStartPart].
+// Union satisfied by [TextPart], [ToolPart], [StepStartPart] or
+// [AssistantMessagePartStepFinishPart].
type AssistantMessagePartUnion interface {
implementsAssistantMessagePart()
}
@@ -505,20 +513,117 @@ func init() {
Type: reflect.TypeOf(StepStartPart{}),
DiscriminatorValue: "step-start",
},
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(AssistantMessagePartStepFinishPart{}),
+ DiscriminatorValue: "step-finish",
+ },
)
}
+type AssistantMessagePartStepFinishPart struct {
+ Cost float64 `json:"cost,required"`
+ Tokens AssistantMessagePartStepFinishPartTokens `json:"tokens,required"`
+ Type AssistantMessagePartStepFinishPartType `json:"type,required"`
+ JSON assistantMessagePartStepFinishPartJSON `json:"-"`
+}
+
+// assistantMessagePartStepFinishPartJSON contains the JSON metadata for the struct
+// [AssistantMessagePartStepFinishPart]
+type assistantMessagePartStepFinishPartJSON struct {
+ Cost apijson.Field
+ Tokens apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessagePartStepFinishPart) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessagePartStepFinishPartJSON) RawJSON() string {
+ return r.raw
+}
+
+func (r AssistantMessagePartStepFinishPart) implementsAssistantMessagePart() {}
+
+type AssistantMessagePartStepFinishPartTokens struct {
+ Cache AssistantMessagePartStepFinishPartTokensCache `json:"cache,required"`
+ Input float64 `json:"input,required"`
+ Output float64 `json:"output,required"`
+ Reasoning float64 `json:"reasoning,required"`
+ JSON assistantMessagePartStepFinishPartTokensJSON `json:"-"`
+}
+
+// assistantMessagePartStepFinishPartTokensJSON contains the JSON metadata for the
+// struct [AssistantMessagePartStepFinishPartTokens]
+type assistantMessagePartStepFinishPartTokensJSON struct {
+ Cache apijson.Field
+ Input apijson.Field
+ Output apijson.Field
+ Reasoning apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessagePartStepFinishPartTokens) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessagePartStepFinishPartTokensJSON) RawJSON() string {
+ return r.raw
+}
+
+type AssistantMessagePartStepFinishPartTokensCache struct {
+ Read float64 `json:"read,required"`
+ Write float64 `json:"write,required"`
+ JSON assistantMessagePartStepFinishPartTokensCacheJSON `json:"-"`
+}
+
+// assistantMessagePartStepFinishPartTokensCacheJSON contains the JSON metadata for
+// the struct [AssistantMessagePartStepFinishPartTokensCache]
+type assistantMessagePartStepFinishPartTokensCacheJSON struct {
+ Read apijson.Field
+ Write apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *AssistantMessagePartStepFinishPartTokensCache) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r assistantMessagePartStepFinishPartTokensCacheJSON) RawJSON() string {
+ return r.raw
+}
+
+type AssistantMessagePartStepFinishPartType string
+
+const (
+ AssistantMessagePartStepFinishPartTypeStepFinish AssistantMessagePartStepFinishPartType = "step-finish"
+)
+
+func (r AssistantMessagePartStepFinishPartType) IsKnown() bool {
+ switch r {
+ case AssistantMessagePartStepFinishPartTypeStepFinish:
+ return true
+ }
+ return false
+}
+
type AssistantMessagePartType string
const (
- AssistantMessagePartTypeText AssistantMessagePartType = "text"
- AssistantMessagePartTypeTool AssistantMessagePartType = "tool"
- AssistantMessagePartTypeStepStart AssistantMessagePartType = "step-start"
+ AssistantMessagePartTypeText AssistantMessagePartType = "text"
+ AssistantMessagePartTypeTool AssistantMessagePartType = "tool"
+ AssistantMessagePartTypeStepStart AssistantMessagePartType = "step-start"
+ AssistantMessagePartTypeStepFinish AssistantMessagePartType = "step-finish"
)
func (r AssistantMessagePartType) IsKnown() bool {
switch r {
- case AssistantMessagePartTypeText, AssistantMessagePartTypeTool, AssistantMessagePartTypeStepStart:
+ case AssistantMessagePartTypeText, AssistantMessagePartTypeTool, AssistantMessagePartTypeStepStart, AssistantMessagePartTypeStepFinish:
return true
}
return false