ignore: more metadata in app info

This commit is contained in:
adamdottv 2025-06-27 06:19:27 -05:00
parent d043f67761
commit 59b3268c64
No known key found for this signature in database
GPG key ID: 9CB48779AF150E75
6 changed files with 558 additions and 77 deletions

View file

@ -19,7 +19,7 @@
},
"packages/opencode": {
"name": "opencode",
"version": "0.0.0",
"version": "0.0.5",
"bin": {
"opencode": "./bin/opencode",
},

View file

@ -2,6 +2,7 @@ import "zod-openapi/extend"
import { Log } from "../util/log"
import { Context } from "../util/context"
import { Filesystem } from "../util/filesystem"
import { Project } from "../util/project"
import { Global } from "../global"
import path from "path"
import os from "os"
@ -12,7 +13,9 @@ export namespace App {
export const Info = z
.object({
project: z.string(),
user: z.string(),
hostname: z.string(),
git: z.boolean(),
path: z.object({
config: z.string(),
@ -62,8 +65,13 @@ export namespace App {
}
>()
const root = git ?? input.cwd
const project = await Project.getName(root)
const info: Info = {
project: project,
user: os.userInfo().username,
hostname: os.hostname(),
time: {
initialized: state.initialized,
},
@ -72,7 +80,7 @@ export namespace App {
config: Global.Path.config,
state: Global.Path.state,
data,
root: git ?? input.cwd,
root,
cwd: input.cwd,
},
}

View file

@ -0,0 +1,91 @@
import path from "path"
import { readdir } from "fs/promises"
export namespace Project {
export async function getName(rootPath: string): Promise<string> {
try {
const packageJsonPath = path.join(rootPath, "package.json")
const packageJson = await Bun.file(packageJsonPath).json()
if (packageJson.name && typeof packageJson.name === "string") {
return packageJson.name
}
} catch {}
try {
const cargoTomlPath = path.join(rootPath, "Cargo.toml")
const cargoToml = await Bun.file(cargoTomlPath).text()
const nameMatch = cargoToml.match(/^\s*name\s*=\s*"([^"]+)"/m)
if (nameMatch?.[1]) {
return nameMatch[1]
}
} catch {}
try {
const pyprojectPath = path.join(rootPath, "pyproject.toml")
const pyproject = await Bun.file(pyprojectPath).text()
const nameMatch = pyproject.match(/^\s*name\s*=\s*"([^"]+)"/m)
if (nameMatch?.[1]) {
return nameMatch[1]
}
} catch {}
try {
const goModPath = path.join(rootPath, "go.mod")
const goMod = await Bun.file(goModPath).text()
const moduleMatch = goMod.match(/^module\s+(.+)$/m)
if (moduleMatch?.[1]) {
// Extract just the last part of the module path
const parts = moduleMatch[1].trim().split("/")
return parts[parts.length - 1]
}
} catch {}
try {
const composerPath = path.join(rootPath, "composer.json")
const composer = await Bun.file(composerPath).json()
if (composer.name && typeof composer.name === "string") {
// Composer names are usually vendor/package, extract the package part
const parts = composer.name.split("/")
return parts[parts.length - 1]
}
} catch {}
try {
const pomPath = path.join(rootPath, "pom.xml")
const pom = await Bun.file(pomPath).text()
const artifactIdMatch = pom.match(/<artifactId>([^<]+)<\/artifactId>/)
if (artifactIdMatch?.[1]) {
return artifactIdMatch[1]
}
} catch {}
for (const gradleFile of ["build.gradle", "build.gradle.kts"]) {
try {
const gradlePath = path.join(rootPath, gradleFile)
await Bun.file(gradlePath).text() // Check if gradle file exists
// Look for rootProject.name in settings.gradle
const settingsPath = path.join(rootPath, "settings.gradle")
const settings = await Bun.file(settingsPath).text()
const nameMatch = settings.match(
/rootProject\.name\s*=\s*['"]([^'"]+)['"]/,
)
if (nameMatch?.[1]) {
return nameMatch[1]
}
} catch {}
}
const dotnetExtensions = [".csproj", ".fsproj", ".vbproj"]
try {
const files = await readdir(rootPath)
for (const file of files) {
if (dotnetExtensions.some((ext) => file.endsWith(ext))) {
// Use the filename without extension as project name
return path.basename(file, path.extname(file))
}
}
} catch {}
return path.basename(rootPath)
}
}

View file

@ -49,6 +49,8 @@ func main() {
logger := slog.New(slog.NewTextHandler(file, &slog.HandlerOptions{Level: slog.LevelDebug}))
slog.SetDefault(logger)
slog.Debug("TUI launched", "app", appInfo)
httpClient, err := client.NewClientWithResponses(url)
if err != nil {
slog.Error("Failed to create client", "error", err)
@ -66,7 +68,6 @@ func main() {
program := tea.NewProgram(
tui.NewModel(app_),
// tea.WithColorProfile(colorprofile.ANSI),
tea.WithAltScreen(),
tea.WithKeyboardEnhancements(),
tea.WithMouseCellMotion(),

View file

@ -115,7 +115,11 @@
"type": "string"
}
},
"required": ["sessionID", "providerID", "modelID"]
"required": [
"sessionID",
"providerID",
"modelID"
]
}
}
}
@ -145,7 +149,12 @@
"type": "string"
}
},
"required": ["root", "data", "cwd", "config"]
"required": [
"root",
"data",
"cwd",
"config"
]
}
}
}
@ -212,7 +221,9 @@
"type": "string"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
}
}
@ -246,7 +257,9 @@
"type": "string"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
}
}
@ -283,7 +296,9 @@
"type": "string"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
}
}
@ -339,7 +354,9 @@
"type": "string"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
}
}
@ -373,7 +390,9 @@
"type": "string"
}
},
"required": ["sessionID"]
"required": [
"sessionID"
]
}
}
}
@ -413,7 +432,11 @@
"type": "string"
}
},
"required": ["sessionID", "providerID", "modelID"]
"required": [
"sessionID",
"providerID",
"modelID"
]
}
}
}
@ -459,7 +482,12 @@
}
}
},
"required": ["sessionID", "providerID", "modelID", "parts"]
"required": [
"sessionID",
"providerID",
"modelID",
"parts"
]
}
}
}
@ -489,7 +517,10 @@
}
}
},
"required": ["providers", "default"]
"required": [
"providers",
"default"
]
}
}
}
@ -530,7 +561,9 @@
"type": "string"
}
},
"required": ["query"]
"required": [
"query"
]
}
}
}
@ -619,10 +652,15 @@
},
"content": {}
},
"required": ["key"]
"required": [
"key"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.installation.updated": {
"type": "object",
@ -638,10 +676,15 @@
"type": "string"
}
},
"required": ["version"]
"required": [
"version"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.lsp.client.diagnostics": {
"type": "object",
@ -660,10 +703,16 @@
"type": "string"
}
},
"required": ["serverID", "path"]
"required": [
"serverID",
"path"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.permission.updated": {
"type": "object",
@ -676,7 +725,10 @@
"$ref": "#/components/schemas/permission.info"
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"permission.info": {
"type": "object",
@ -701,10 +753,18 @@
"type": "number"
}
},
"required": ["created"]
"required": [
"created"
]
}
},
"required": ["id", "sessionID", "title", "metadata", "time"]
"required": [
"id",
"sessionID",
"title",
"metadata",
"time"
]
},
"Event.message.updated": {
"type": "object",
@ -720,10 +780,15 @@
"$ref": "#/components/schemas/Message.Info"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Message.Info": {
"type": "object",
@ -733,7 +798,10 @@
},
"role": {
"type": "string",
"enum": ["user", "assistant"]
"enum": [
"user",
"assistant"
]
},
"parts": {
"type": "array",
@ -745,7 +813,12 @@
"$ref": "#/components/schemas/Message.Metadata"
}
},
"required": ["id", "role", "parts", "metadata"]
"required": [
"id",
"role",
"parts",
"metadata"
]
},
"Message.Part": {
"oneOf": [
@ -791,7 +864,10 @@
"type": "string"
}
},
"required": ["type", "text"]
"required": [
"type",
"text"
]
},
"Message.Part.Reasoning": {
"type": "object",
@ -808,7 +884,10 @@
"additionalProperties": {}
}
},
"required": ["type", "text"]
"required": [
"type",
"text"
]
},
"Message.Part.ToolInvocation": {
"type": "object",
@ -821,7 +900,10 @@
"$ref": "#/components/schemas/Message.ToolInvocation"
}
},
"required": ["type", "toolInvocation"]
"required": [
"type",
"toolInvocation"
]
},
"Message.ToolInvocation": {
"oneOf": [
@ -862,7 +944,11 @@
},
"args": {}
},
"required": ["state", "toolCallId", "toolName"]
"required": [
"state",
"toolCallId",
"toolName"
]
},
"Message.ToolInvocation.ToolPartialCall": {
"type": "object",
@ -882,7 +968,11 @@
},
"args": {}
},
"required": ["state", "toolCallId", "toolName"]
"required": [
"state",
"toolCallId",
"toolName"
]
},
"Message.ToolInvocation.ToolResult": {
"type": "object",
@ -905,7 +995,12 @@
"type": "string"
}
},
"required": ["state", "toolCallId", "toolName", "result"]
"required": [
"state",
"toolCallId",
"toolName",
"result"
]
},
"Message.Part.SourceUrl": {
"type": "object",
@ -928,7 +1023,11 @@
"additionalProperties": {}
}
},
"required": ["type", "sourceId", "url"]
"required": [
"type",
"sourceId",
"url"
]
},
"Message.Part.File": {
"type": "object",
@ -947,7 +1046,11 @@
"type": "string"
}
},
"required": ["type", "mediaType", "url"]
"required": [
"type",
"mediaType",
"url"
]
},
"Message.Part.StepStart": {
"type": "object",
@ -957,7 +1060,9 @@
"const": "step-start"
}
},
"required": ["type"]
"required": [
"type"
]
},
"Message.Metadata": {
"type": "object",
@ -972,7 +1077,9 @@
"type": "number"
}
},
"required": ["created"]
"required": [
"created"
]
},
"error": {
"oneOf": [
@ -981,13 +1088,17 @@
},
{
"$ref": "#/components/schemas/UnknownError"
},
{
"$ref": "#/components/schemas/MessageOutputLengthError"
}
],
"discriminator": {
"propertyName": "name",
"mapping": {
"ProviderAuthError": "#/components/schemas/ProviderAuthError",
"UnknownError": "#/components/schemas/UnknownError"
"UnknownError": "#/components/schemas/UnknownError",
"MessageOutputLengthError": "#/components/schemas/MessageOutputLengthError"
}
}
},
@ -1012,10 +1123,16 @@
"type": "number"
}
},
"required": ["start", "end"]
"required": [
"start",
"end"
]
}
},
"required": ["title", "time"],
"required": [
"title",
"time"
],
"additionalProperties": {}
}
},
@ -1044,7 +1161,10 @@
"type": "string"
}
},
"required": ["cwd", "root"]
"required": [
"cwd",
"root"
]
},
"cost": {
"type": "number"
@ -1074,10 +1194,18 @@
"type": "number"
}
},
"required": ["read", "write"]
"required": [
"read",
"write"
]
}
},
"required": ["input", "output", "reasoning", "cache"]
"required": [
"input",
"output",
"reasoning",
"cache"
]
}
},
"required": [
@ -1090,7 +1218,11 @@
]
}
},
"required": ["time", "sessionID", "tool"]
"required": [
"time",
"sessionID",
"tool"
]
},
"ProviderAuthError": {
"type": "object",
@ -1109,10 +1241,16 @@
"type": "string"
}
},
"required": ["providerID", "message"]
"required": [
"providerID",
"message"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"UnknownError": {
"type": "object",
@ -1128,10 +1266,31 @@
"type": "string"
}
},
"required": ["message"]
"required": [
"message"
]
}
},
"required": ["name", "data"]
"required": [
"name",
"data"
]
},
"MessageOutputLengthError": {
"type": "object",
"properties": {
"name": {
"type": "string",
"const": "MessageOutputLengthError"
},
"data": {
"type": "object"
}
},
"required": [
"name",
"data"
]
},
"Event.message.part.updated": {
"type": "object",
@ -1153,10 +1312,17 @@
"type": "string"
}
},
"required": ["part", "sessionID", "messageID"]
"required": [
"part",
"sessionID",
"messageID"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.updated": {
"type": "object",
@ -1172,10 +1338,15 @@
"$ref": "#/components/schemas/session.info"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"session.info": {
"type": "object",
@ -1195,7 +1366,9 @@
"type": "string"
}
},
"required": ["url"]
"required": [
"url"
]
},
"title": {
"type": "string"
@ -1213,10 +1386,18 @@
"type": "number"
}
},
"required": ["created", "updated"]
"required": [
"created",
"updated"
]
}
},
"required": ["id", "title", "version", "time"]
"required": [
"id",
"title",
"version",
"time"
]
},
"Event.session.deleted": {
"type": "object",
@ -1232,10 +1413,15 @@
"$ref": "#/components/schemas/session.info"
}
},
"required": ["info"]
"required": [
"info"
]
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"Event.session.error": {
"type": "object",
@ -1254,27 +1440,40 @@
},
{
"$ref": "#/components/schemas/UnknownError"
},
{
"$ref": "#/components/schemas/MessageOutputLengthError"
}
],
"discriminator": {
"propertyName": "name",
"mapping": {
"ProviderAuthError": "#/components/schemas/ProviderAuthError",
"UnknownError": "#/components/schemas/UnknownError"
"UnknownError": "#/components/schemas/UnknownError",
"MessageOutputLengthError": "#/components/schemas/MessageOutputLengthError"
}
}
}
}
}
},
"required": ["type", "properties"]
"required": [
"type",
"properties"
]
},
"App.Info": {
"type": "object",
"properties": {
"project": {
"type": "string"
},
"user": {
"type": "string"
},
"hostname": {
"type": "string"
},
"git": {
"type": "boolean"
},
@ -1297,7 +1496,13 @@
"type": "string"
}
},
"required": ["config", "data", "root", "cwd", "state"]
"required": [
"config",
"data",
"root",
"cwd",
"state"
]
},
"time": {
"type": "object",
@ -1308,7 +1513,14 @@
}
}
},
"required": ["user", "git", "path", "time"]
"required": [
"project",
"user",
"hostname",
"git",
"path",
"time"
]
},
"Config.Info": {
"type": "object",
@ -1403,7 +1615,10 @@
"type": "number"
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
},
"limit": {
"type": "object",
@ -1415,7 +1630,10 @@
"type": "number"
}
},
"required": ["context", "output"]
"required": [
"context",
"output"
]
},
"id": {
"type": "string"
@ -1432,7 +1650,9 @@
"additionalProperties": {}
}
},
"required": ["models"]
"required": [
"models"
]
},
"description": "Custom provider configurations and model overrides"
},
@ -1456,6 +1676,65 @@
}
},
"description": "MCP (Model Context Protocol) server configurations"
},
"experimental": {
"type": "object",
"properties": {
"hook": {
"type": "object",
"properties": {
"file_edited": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"properties": {
"command": {
"type": "array",
"items": {
"type": "string"
}
},
"environment": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"required": [
"command"
]
}
}
},
"session_completed": {
"type": "array",
"items": {
"type": "object",
"properties": {
"command": {
"type": "array",
"items": {
"type": "string"
}
},
"environment": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"required": [
"command"
]
}
}
}
}
}
}
},
"additionalProperties": false
@ -1602,7 +1881,12 @@
}
}
},
"required": ["name", "env", "id", "models"]
"required": [
"name",
"env",
"id",
"models"
]
},
"Model.Info": {
"type": "object",
@ -1638,7 +1922,10 @@
"type": "number"
}
},
"required": ["input", "output"]
"required": [
"input",
"output"
]
},
"limit": {
"type": "object",
@ -1650,7 +1937,10 @@
"type": "number"
}
},
"required": ["context", "output"]
"required": [
"context",
"output"
]
},
"id": {
"type": "string"
@ -1695,7 +1985,10 @@
"description": "Environment variables to set when running the MCP server"
}
},
"required": ["type", "command"],
"required": [
"type",
"command"
],
"additionalProperties": false
},
"Config.McpRemote": {
@ -1711,7 +2004,10 @@
"description": "URL of the remote MCP server"
}
},
"required": ["type", "url"],
"required": [
"type",
"url"
],
"additionalProperties": false
},
"Error": {
@ -1722,7 +2018,9 @@
"additionalProperties": {}
}
},
"required": ["data"]
"required": [
"data"
]
},
"InstallationInfo": {
"type": "object",
@ -1734,8 +2032,11 @@
"type": "string"
}
},
"required": ["version", "latest"]
"required": [
"version",
"latest"
]
}
}
}
}
}

View file

@ -25,15 +25,17 @@ const (
// AppInfo defines model for App.Info.
type AppInfo struct {
Git bool `json:"git"`
Path struct {
Git bool `json:"git"`
Hostname string `json:"hostname"`
Path struct {
Config string `json:"config"`
Cwd string `json:"cwd"`
Data string `json:"data"`
Root string `json:"root"`
State string `json:"state"`
} `json:"path"`
Time struct {
Project string `json:"project"`
Time struct {
Initialized *float32 `json:"initialized,omitempty"`
} `json:"time"`
User string `json:"user"`
@ -51,8 +53,20 @@ type ConfigInfo struct {
Autoupdate *bool `json:"autoupdate,omitempty"`
// DisabledProviders Disable providers that are loaded automatically
DisabledProviders *[]string `json:"disabled_providers,omitempty"`
Keybinds *ConfigKeybinds `json:"keybinds,omitempty"`
DisabledProviders *[]string `json:"disabled_providers,omitempty"`
Experimental *struct {
Hook *struct {
FileEdited *map[string][]struct {
Command []string `json:"command"`
Environment *map[string]string `json:"environment,omitempty"`
} `json:"file_edited,omitempty"`
SessionCompleted *[]struct {
Command []string `json:"command"`
Environment *map[string]string `json:"environment,omitempty"`
} `json:"session_completed,omitempty"`
} `json:"hook,omitempty"`
} `json:"experimental,omitempty"`
Keybinds *ConfigKeybinds `json:"keybinds,omitempty"`
// Mcp MCP (Model Context Protocol) server configurations
Mcp *map[string]ConfigInfo_Mcp_AdditionalProperties `json:"mcp,omitempty"`
@ -434,6 +448,12 @@ type MessageToolInvocationToolResult struct {
ToolName string `json:"toolName"`
}
// MessageOutputLengthError defines model for MessageOutputLengthError.
type MessageOutputLengthError struct {
Data map[string]interface{} `json:"data"`
Name string `json:"name"`
}
// ModelInfo defines model for Model.Info.
type ModelInfo struct {
Attachment bool `json:"attachment"`
@ -1110,6 +1130,34 @@ func (t *EventSessionError_Properties_Error) MergeUnknownError(v UnknownError) e
return err
}
// AsMessageOutputLengthError returns the union data inside the EventSessionError_Properties_Error as a MessageOutputLengthError
func (t EventSessionError_Properties_Error) AsMessageOutputLengthError() (MessageOutputLengthError, error) {
var body MessageOutputLengthError
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromMessageOutputLengthError overwrites any union data inside the EventSessionError_Properties_Error as the provided MessageOutputLengthError
func (t *EventSessionError_Properties_Error) FromMessageOutputLengthError(v MessageOutputLengthError) error {
v.Name = "MessageOutputLengthError"
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeMessageOutputLengthError performs a merge with any union data inside the EventSessionError_Properties_Error, using the provided MessageOutputLengthError
func (t *EventSessionError_Properties_Error) MergeMessageOutputLengthError(v MessageOutputLengthError) error {
v.Name = "MessageOutputLengthError"
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t EventSessionError_Properties_Error) Discriminator() (string, error) {
var discriminator struct {
Discriminator string `json:"name"`
@ -1124,6 +1172,8 @@ func (t EventSessionError_Properties_Error) ValueByDiscriminator() (interface{},
return nil, err
}
switch discriminator {
case "MessageOutputLengthError":
return t.AsMessageOutputLengthError()
case "ProviderAuthError":
return t.AsProviderAuthError()
case "UnknownError":
@ -1199,6 +1249,34 @@ func (t *MessageMetadata_Error) MergeUnknownError(v UnknownError) error {
return err
}
// AsMessageOutputLengthError returns the union data inside the MessageMetadata_Error as a MessageOutputLengthError
func (t MessageMetadata_Error) AsMessageOutputLengthError() (MessageOutputLengthError, error) {
var body MessageOutputLengthError
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromMessageOutputLengthError overwrites any union data inside the MessageMetadata_Error as the provided MessageOutputLengthError
func (t *MessageMetadata_Error) FromMessageOutputLengthError(v MessageOutputLengthError) error {
v.Name = "MessageOutputLengthError"
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeMessageOutputLengthError performs a merge with any union data inside the MessageMetadata_Error, using the provided MessageOutputLengthError
func (t *MessageMetadata_Error) MergeMessageOutputLengthError(v MessageOutputLengthError) error {
v.Name = "MessageOutputLengthError"
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t MessageMetadata_Error) Discriminator() (string, error) {
var discriminator struct {
Discriminator string `json:"name"`
@ -1213,6 +1291,8 @@ func (t MessageMetadata_Error) ValueByDiscriminator() (interface{}, error) {
return nil, err
}
switch discriminator {
case "MessageOutputLengthError":
return t.AsMessageOutputLengthError()
case "ProviderAuthError":
return t.AsProviderAuthError()
case "UnknownError":