mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-19 08:44:22 +01:00
feat: bash commands
This commit is contained in:
@@ -1050,14 +1050,15 @@ export namespace Session {
|
||||
}
|
||||
await updatePart(part)
|
||||
const app = App.info()
|
||||
const process = exec(input.command, {
|
||||
const proc = exec(input.command, {
|
||||
cwd: app.path.cwd,
|
||||
signal: abort.signal,
|
||||
shell: process.env["SHELL"],
|
||||
})
|
||||
|
||||
let output = ""
|
||||
|
||||
process.stdout?.on("data", (chunk) => {
|
||||
proc.stdout?.on("data", (chunk) => {
|
||||
output += chunk.toString()
|
||||
if (part.state.status === "running") {
|
||||
part.state.metadata = {
|
||||
@@ -1068,7 +1069,7 @@ export namespace Session {
|
||||
}
|
||||
})
|
||||
|
||||
process.stderr?.on("data", (chunk) => {
|
||||
proc.stderr?.on("data", (chunk) => {
|
||||
output += chunk.toString()
|
||||
if (part.state.status === "running") {
|
||||
part.state.metadata = {
|
||||
@@ -1080,7 +1081,7 @@ export namespace Session {
|
||||
})
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
process.on("close", () => {
|
||||
proc.on("close", () => {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
configured_endpoints: 34
|
||||
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-b86cf7bb8df4f60ebe8b8f51e281c8076cfdccc8554178c1b78beca4b025f0ff.yml
|
||||
openapi_spec_hash: 47633b7481d91708643ea7b43fffffe6
|
||||
config_hash: bd7f6435ed0c0005f373b5526c07a055
|
||||
configured_endpoints: 36
|
||||
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-9031231386199b2baadcaaed5b8df17899f8bc82efef4a74d7a0646fc035268a.yml
|
||||
openapi_spec_hash: 8ef902a2a7039a4a6fde44ee7c26c87d
|
||||
config_hash: 2b388a88fa9da825b43cbc25c2b349b5
|
||||
|
||||
@@ -111,9 +111,11 @@ Response Types:
|
||||
Methods:
|
||||
|
||||
- <code title="post /session">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="patch /session/{id}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Update">Update</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionUpdateParams">SessionUpdateParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="get /session">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="delete /session/{id}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/abort">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Abort">Abort</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/bash">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Bash">Bash</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionBashParams">SessionBashParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Chat">Chat</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChatParams">SessionChatParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="post /session/{id}/init">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Init">Init</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionInitParams">SessionInitParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
- <code title="get /session/{id}/message/{messageID}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Message">Message</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, messageID <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionMessageResponse">SessionMessageResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
|
||||
|
||||
@@ -74,6 +74,8 @@ func (r *AppService) Providers(ctx context.Context, opts ...option.RequestOption
|
||||
type Agent struct {
|
||||
Mode AgentMode `json:"mode,required"`
|
||||
Name string `json:"name,required"`
|
||||
Options map[string]interface{} `json:"options,required"`
|
||||
Permission AgentPermission `json:"permission,required"`
|
||||
Tools map[string]bool `json:"tools,required"`
|
||||
Description string `json:"description"`
|
||||
Model AgentModel `json:"model"`
|
||||
@@ -87,6 +89,8 @@ type Agent struct {
|
||||
type agentJSON struct {
|
||||
Mode apijson.Field
|
||||
Name apijson.Field
|
||||
Options apijson.Field
|
||||
Permission apijson.Field
|
||||
Tools apijson.Field
|
||||
Description apijson.Field
|
||||
Model apijson.Field
|
||||
@@ -121,6 +125,78 @@ func (r AgentMode) IsKnown() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type AgentPermission struct {
|
||||
Bash map[string]AgentPermissionBash `json:"bash,required"`
|
||||
Edit AgentPermissionEdit `json:"edit,required"`
|
||||
Webfetch AgentPermissionWebfetch `json:"webfetch"`
|
||||
JSON agentPermissionJSON `json:"-"`
|
||||
}
|
||||
|
||||
// agentPermissionJSON contains the JSON metadata for the struct [AgentPermission]
|
||||
type agentPermissionJSON struct {
|
||||
Bash apijson.Field
|
||||
Edit apijson.Field
|
||||
Webfetch apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *AgentPermission) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r agentPermissionJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
type AgentPermissionBash string
|
||||
|
||||
const (
|
||||
AgentPermissionBashAsk AgentPermissionBash = "ask"
|
||||
AgentPermissionBashAllow AgentPermissionBash = "allow"
|
||||
AgentPermissionBashDeny AgentPermissionBash = "deny"
|
||||
)
|
||||
|
||||
func (r AgentPermissionBash) IsKnown() bool {
|
||||
switch r {
|
||||
case AgentPermissionBashAsk, AgentPermissionBashAllow, AgentPermissionBashDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type AgentPermissionEdit string
|
||||
|
||||
const (
|
||||
AgentPermissionEditAsk AgentPermissionEdit = "ask"
|
||||
AgentPermissionEditAllow AgentPermissionEdit = "allow"
|
||||
AgentPermissionEditDeny AgentPermissionEdit = "deny"
|
||||
)
|
||||
|
||||
func (r AgentPermissionEdit) IsKnown() bool {
|
||||
switch r {
|
||||
case AgentPermissionEditAsk, AgentPermissionEditAllow, AgentPermissionEditDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type AgentPermissionWebfetch string
|
||||
|
||||
const (
|
||||
AgentPermissionWebfetchAsk AgentPermissionWebfetch = "ask"
|
||||
AgentPermissionWebfetchAllow AgentPermissionWebfetch = "allow"
|
||||
AgentPermissionWebfetchDeny AgentPermissionWebfetch = "deny"
|
||||
)
|
||||
|
||||
func (r AgentPermissionWebfetch) IsKnown() bool {
|
||||
switch r {
|
||||
case AgentPermissionWebfetchAsk, AgentPermissionWebfetchAllow, AgentPermissionWebfetchDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type AgentModel struct {
|
||||
ModelID string `json:"modelID,required"`
|
||||
ProviderID string `json:"providerID,required"`
|
||||
|
||||
@@ -153,10 +153,12 @@ type ConfigAgentBuild struct {
|
||||
Disable bool `json:"disable"`
|
||||
Mode ConfigAgentBuildMode `json:"mode"`
|
||||
Model string `json:"model"`
|
||||
Permission ConfigAgentBuildPermission `json:"permission"`
|
||||
Prompt string `json:"prompt"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
Tools map[string]bool `json:"tools"`
|
||||
TopP float64 `json:"top_p"`
|
||||
ExtraFields map[string]interface{} `json:"-,extras"`
|
||||
JSON configAgentBuildJSON `json:"-"`
|
||||
}
|
||||
|
||||
@@ -167,6 +169,7 @@ type configAgentBuildJSON struct {
|
||||
Disable apijson.Field
|
||||
Mode apijson.Field
|
||||
Model apijson.Field
|
||||
Permission apijson.Field
|
||||
Prompt apijson.Field
|
||||
Temperature apijson.Field
|
||||
Tools apijson.Field
|
||||
@@ -199,16 +202,134 @@ func (r ConfigAgentBuildMode) IsKnown() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentBuildPermission struct {
|
||||
Bash ConfigAgentBuildPermissionBashUnion `json:"bash"`
|
||||
Edit ConfigAgentBuildPermissionEdit `json:"edit"`
|
||||
Webfetch ConfigAgentBuildPermissionWebfetch `json:"webfetch"`
|
||||
JSON configAgentBuildPermissionJSON `json:"-"`
|
||||
}
|
||||
|
||||
// configAgentBuildPermissionJSON contains the JSON metadata for the struct
|
||||
// [ConfigAgentBuildPermission]
|
||||
type configAgentBuildPermissionJSON struct {
|
||||
Bash apijson.Field
|
||||
Edit apijson.Field
|
||||
Webfetch apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *ConfigAgentBuildPermission) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r configAgentBuildPermissionJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
// Union satisfied by [ConfigAgentBuildPermissionBashString] or
|
||||
// [ConfigAgentBuildPermissionBashMap].
|
||||
type ConfigAgentBuildPermissionBashUnion interface {
|
||||
implementsConfigAgentBuildPermissionBashUnion()
|
||||
}
|
||||
|
||||
func init() {
|
||||
apijson.RegisterUnion(
|
||||
reflect.TypeOf((*ConfigAgentBuildPermissionBashUnion)(nil)).Elem(),
|
||||
"",
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.String,
|
||||
Type: reflect.TypeOf(ConfigAgentBuildPermissionBashString("")),
|
||||
},
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.JSON,
|
||||
Type: reflect.TypeOf(ConfigAgentBuildPermissionBashMap{}),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type ConfigAgentBuildPermissionBashString string
|
||||
|
||||
const (
|
||||
ConfigAgentBuildPermissionBashStringAsk ConfigAgentBuildPermissionBashString = "ask"
|
||||
ConfigAgentBuildPermissionBashStringAllow ConfigAgentBuildPermissionBashString = "allow"
|
||||
ConfigAgentBuildPermissionBashStringDeny ConfigAgentBuildPermissionBashString = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentBuildPermissionBashString) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentBuildPermissionBashStringAsk, ConfigAgentBuildPermissionBashStringAllow, ConfigAgentBuildPermissionBashStringDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r ConfigAgentBuildPermissionBashString) implementsConfigAgentBuildPermissionBashUnion() {}
|
||||
|
||||
type ConfigAgentBuildPermissionBashMap map[string]ConfigAgentBuildPermissionBashMapItem
|
||||
|
||||
func (r ConfigAgentBuildPermissionBashMap) implementsConfigAgentBuildPermissionBashUnion() {}
|
||||
|
||||
type ConfigAgentBuildPermissionBashMapItem string
|
||||
|
||||
const (
|
||||
ConfigAgentBuildPermissionBashMapAsk ConfigAgentBuildPermissionBashMapItem = "ask"
|
||||
ConfigAgentBuildPermissionBashMapAllow ConfigAgentBuildPermissionBashMapItem = "allow"
|
||||
ConfigAgentBuildPermissionBashMapDeny ConfigAgentBuildPermissionBashMapItem = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentBuildPermissionBashMapItem) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentBuildPermissionBashMapAsk, ConfigAgentBuildPermissionBashMapAllow, ConfigAgentBuildPermissionBashMapDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentBuildPermissionEdit string
|
||||
|
||||
const (
|
||||
ConfigAgentBuildPermissionEditAsk ConfigAgentBuildPermissionEdit = "ask"
|
||||
ConfigAgentBuildPermissionEditAllow ConfigAgentBuildPermissionEdit = "allow"
|
||||
ConfigAgentBuildPermissionEditDeny ConfigAgentBuildPermissionEdit = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentBuildPermissionEdit) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentBuildPermissionEditAsk, ConfigAgentBuildPermissionEditAllow, ConfigAgentBuildPermissionEditDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentBuildPermissionWebfetch string
|
||||
|
||||
const (
|
||||
ConfigAgentBuildPermissionWebfetchAsk ConfigAgentBuildPermissionWebfetch = "ask"
|
||||
ConfigAgentBuildPermissionWebfetchAllow ConfigAgentBuildPermissionWebfetch = "allow"
|
||||
ConfigAgentBuildPermissionWebfetchDeny ConfigAgentBuildPermissionWebfetch = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentBuildPermissionWebfetch) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentBuildPermissionWebfetchAsk, ConfigAgentBuildPermissionWebfetchAllow, ConfigAgentBuildPermissionWebfetchDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentGeneral struct {
|
||||
// Description of when to use the agent
|
||||
Description string `json:"description"`
|
||||
Disable bool `json:"disable"`
|
||||
Mode ConfigAgentGeneralMode `json:"mode"`
|
||||
Model string `json:"model"`
|
||||
Permission ConfigAgentGeneralPermission `json:"permission"`
|
||||
Prompt string `json:"prompt"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
Tools map[string]bool `json:"tools"`
|
||||
TopP float64 `json:"top_p"`
|
||||
ExtraFields map[string]interface{} `json:"-,extras"`
|
||||
JSON configAgentGeneralJSON `json:"-"`
|
||||
}
|
||||
|
||||
@@ -219,6 +340,7 @@ type configAgentGeneralJSON struct {
|
||||
Disable apijson.Field
|
||||
Mode apijson.Field
|
||||
Model apijson.Field
|
||||
Permission apijson.Field
|
||||
Prompt apijson.Field
|
||||
Temperature apijson.Field
|
||||
Tools apijson.Field
|
||||
@@ -251,16 +373,134 @@ func (r ConfigAgentGeneralMode) IsKnown() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentGeneralPermission struct {
|
||||
Bash ConfigAgentGeneralPermissionBashUnion `json:"bash"`
|
||||
Edit ConfigAgentGeneralPermissionEdit `json:"edit"`
|
||||
Webfetch ConfigAgentGeneralPermissionWebfetch `json:"webfetch"`
|
||||
JSON configAgentGeneralPermissionJSON `json:"-"`
|
||||
}
|
||||
|
||||
// configAgentGeneralPermissionJSON contains the JSON metadata for the struct
|
||||
// [ConfigAgentGeneralPermission]
|
||||
type configAgentGeneralPermissionJSON struct {
|
||||
Bash apijson.Field
|
||||
Edit apijson.Field
|
||||
Webfetch apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *ConfigAgentGeneralPermission) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r configAgentGeneralPermissionJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
// Union satisfied by [ConfigAgentGeneralPermissionBashString] or
|
||||
// [ConfigAgentGeneralPermissionBashMap].
|
||||
type ConfigAgentGeneralPermissionBashUnion interface {
|
||||
implementsConfigAgentGeneralPermissionBashUnion()
|
||||
}
|
||||
|
||||
func init() {
|
||||
apijson.RegisterUnion(
|
||||
reflect.TypeOf((*ConfigAgentGeneralPermissionBashUnion)(nil)).Elem(),
|
||||
"",
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.String,
|
||||
Type: reflect.TypeOf(ConfigAgentGeneralPermissionBashString("")),
|
||||
},
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.JSON,
|
||||
Type: reflect.TypeOf(ConfigAgentGeneralPermissionBashMap{}),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type ConfigAgentGeneralPermissionBashString string
|
||||
|
||||
const (
|
||||
ConfigAgentGeneralPermissionBashStringAsk ConfigAgentGeneralPermissionBashString = "ask"
|
||||
ConfigAgentGeneralPermissionBashStringAllow ConfigAgentGeneralPermissionBashString = "allow"
|
||||
ConfigAgentGeneralPermissionBashStringDeny ConfigAgentGeneralPermissionBashString = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentGeneralPermissionBashString) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentGeneralPermissionBashStringAsk, ConfigAgentGeneralPermissionBashStringAllow, ConfigAgentGeneralPermissionBashStringDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r ConfigAgentGeneralPermissionBashString) implementsConfigAgentGeneralPermissionBashUnion() {}
|
||||
|
||||
type ConfigAgentGeneralPermissionBashMap map[string]ConfigAgentGeneralPermissionBashMapItem
|
||||
|
||||
func (r ConfigAgentGeneralPermissionBashMap) implementsConfigAgentGeneralPermissionBashUnion() {}
|
||||
|
||||
type ConfigAgentGeneralPermissionBashMapItem string
|
||||
|
||||
const (
|
||||
ConfigAgentGeneralPermissionBashMapAsk ConfigAgentGeneralPermissionBashMapItem = "ask"
|
||||
ConfigAgentGeneralPermissionBashMapAllow ConfigAgentGeneralPermissionBashMapItem = "allow"
|
||||
ConfigAgentGeneralPermissionBashMapDeny ConfigAgentGeneralPermissionBashMapItem = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentGeneralPermissionBashMapItem) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentGeneralPermissionBashMapAsk, ConfigAgentGeneralPermissionBashMapAllow, ConfigAgentGeneralPermissionBashMapDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentGeneralPermissionEdit string
|
||||
|
||||
const (
|
||||
ConfigAgentGeneralPermissionEditAsk ConfigAgentGeneralPermissionEdit = "ask"
|
||||
ConfigAgentGeneralPermissionEditAllow ConfigAgentGeneralPermissionEdit = "allow"
|
||||
ConfigAgentGeneralPermissionEditDeny ConfigAgentGeneralPermissionEdit = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentGeneralPermissionEdit) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentGeneralPermissionEditAsk, ConfigAgentGeneralPermissionEditAllow, ConfigAgentGeneralPermissionEditDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentGeneralPermissionWebfetch string
|
||||
|
||||
const (
|
||||
ConfigAgentGeneralPermissionWebfetchAsk ConfigAgentGeneralPermissionWebfetch = "ask"
|
||||
ConfigAgentGeneralPermissionWebfetchAllow ConfigAgentGeneralPermissionWebfetch = "allow"
|
||||
ConfigAgentGeneralPermissionWebfetchDeny ConfigAgentGeneralPermissionWebfetch = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentGeneralPermissionWebfetch) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentGeneralPermissionWebfetchAsk, ConfigAgentGeneralPermissionWebfetchAllow, ConfigAgentGeneralPermissionWebfetchDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentPlan struct {
|
||||
// Description of when to use the agent
|
||||
Description string `json:"description"`
|
||||
Disable bool `json:"disable"`
|
||||
Mode ConfigAgentPlanMode `json:"mode"`
|
||||
Model string `json:"model"`
|
||||
Permission ConfigAgentPlanPermission `json:"permission"`
|
||||
Prompt string `json:"prompt"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
Tools map[string]bool `json:"tools"`
|
||||
TopP float64 `json:"top_p"`
|
||||
ExtraFields map[string]interface{} `json:"-,extras"`
|
||||
JSON configAgentPlanJSON `json:"-"`
|
||||
}
|
||||
|
||||
@@ -270,6 +510,7 @@ type configAgentPlanJSON struct {
|
||||
Disable apijson.Field
|
||||
Mode apijson.Field
|
||||
Model apijson.Field
|
||||
Permission apijson.Field
|
||||
Prompt apijson.Field
|
||||
Temperature apijson.Field
|
||||
Tools apijson.Field
|
||||
@@ -302,6 +543,122 @@ func (r ConfigAgentPlanMode) IsKnown() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentPlanPermission struct {
|
||||
Bash ConfigAgentPlanPermissionBashUnion `json:"bash"`
|
||||
Edit ConfigAgentPlanPermissionEdit `json:"edit"`
|
||||
Webfetch ConfigAgentPlanPermissionWebfetch `json:"webfetch"`
|
||||
JSON configAgentPlanPermissionJSON `json:"-"`
|
||||
}
|
||||
|
||||
// configAgentPlanPermissionJSON contains the JSON metadata for the struct
|
||||
// [ConfigAgentPlanPermission]
|
||||
type configAgentPlanPermissionJSON struct {
|
||||
Bash apijson.Field
|
||||
Edit apijson.Field
|
||||
Webfetch apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *ConfigAgentPlanPermission) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r configAgentPlanPermissionJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
// Union satisfied by [ConfigAgentPlanPermissionBashString] or
|
||||
// [ConfigAgentPlanPermissionBashMap].
|
||||
type ConfigAgentPlanPermissionBashUnion interface {
|
||||
implementsConfigAgentPlanPermissionBashUnion()
|
||||
}
|
||||
|
||||
func init() {
|
||||
apijson.RegisterUnion(
|
||||
reflect.TypeOf((*ConfigAgentPlanPermissionBashUnion)(nil)).Elem(),
|
||||
"",
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.String,
|
||||
Type: reflect.TypeOf(ConfigAgentPlanPermissionBashString("")),
|
||||
},
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.JSON,
|
||||
Type: reflect.TypeOf(ConfigAgentPlanPermissionBashMap{}),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type ConfigAgentPlanPermissionBashString string
|
||||
|
||||
const (
|
||||
ConfigAgentPlanPermissionBashStringAsk ConfigAgentPlanPermissionBashString = "ask"
|
||||
ConfigAgentPlanPermissionBashStringAllow ConfigAgentPlanPermissionBashString = "allow"
|
||||
ConfigAgentPlanPermissionBashStringDeny ConfigAgentPlanPermissionBashString = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentPlanPermissionBashString) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentPlanPermissionBashStringAsk, ConfigAgentPlanPermissionBashStringAllow, ConfigAgentPlanPermissionBashStringDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r ConfigAgentPlanPermissionBashString) implementsConfigAgentPlanPermissionBashUnion() {}
|
||||
|
||||
type ConfigAgentPlanPermissionBashMap map[string]ConfigAgentPlanPermissionBashMapItem
|
||||
|
||||
func (r ConfigAgentPlanPermissionBashMap) implementsConfigAgentPlanPermissionBashUnion() {}
|
||||
|
||||
type ConfigAgentPlanPermissionBashMapItem string
|
||||
|
||||
const (
|
||||
ConfigAgentPlanPermissionBashMapAsk ConfigAgentPlanPermissionBashMapItem = "ask"
|
||||
ConfigAgentPlanPermissionBashMapAllow ConfigAgentPlanPermissionBashMapItem = "allow"
|
||||
ConfigAgentPlanPermissionBashMapDeny ConfigAgentPlanPermissionBashMapItem = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentPlanPermissionBashMapItem) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentPlanPermissionBashMapAsk, ConfigAgentPlanPermissionBashMapAllow, ConfigAgentPlanPermissionBashMapDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentPlanPermissionEdit string
|
||||
|
||||
const (
|
||||
ConfigAgentPlanPermissionEditAsk ConfigAgentPlanPermissionEdit = "ask"
|
||||
ConfigAgentPlanPermissionEditAllow ConfigAgentPlanPermissionEdit = "allow"
|
||||
ConfigAgentPlanPermissionEditDeny ConfigAgentPlanPermissionEdit = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentPlanPermissionEdit) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentPlanPermissionEditAsk, ConfigAgentPlanPermissionEditAllow, ConfigAgentPlanPermissionEditDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigAgentPlanPermissionWebfetch string
|
||||
|
||||
const (
|
||||
ConfigAgentPlanPermissionWebfetchAsk ConfigAgentPlanPermissionWebfetch = "ask"
|
||||
ConfigAgentPlanPermissionWebfetchAllow ConfigAgentPlanPermissionWebfetch = "allow"
|
||||
ConfigAgentPlanPermissionWebfetchDeny ConfigAgentPlanPermissionWebfetch = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigAgentPlanPermissionWebfetch) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigAgentPlanPermissionWebfetchAsk, ConfigAgentPlanPermissionWebfetchAllow, ConfigAgentPlanPermissionWebfetchDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigExperimental struct {
|
||||
Hook ConfigExperimentalHook `json:"hook"`
|
||||
JSON configExperimentalJSON `json:"-"`
|
||||
@@ -685,10 +1042,12 @@ type ConfigModeBuild struct {
|
||||
Disable bool `json:"disable"`
|
||||
Mode ConfigModeBuildMode `json:"mode"`
|
||||
Model string `json:"model"`
|
||||
Permission ConfigModeBuildPermission `json:"permission"`
|
||||
Prompt string `json:"prompt"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
Tools map[string]bool `json:"tools"`
|
||||
TopP float64 `json:"top_p"`
|
||||
ExtraFields map[string]interface{} `json:"-,extras"`
|
||||
JSON configModeBuildJSON `json:"-"`
|
||||
}
|
||||
|
||||
@@ -698,6 +1057,7 @@ type configModeBuildJSON struct {
|
||||
Disable apijson.Field
|
||||
Mode apijson.Field
|
||||
Model apijson.Field
|
||||
Permission apijson.Field
|
||||
Prompt apijson.Field
|
||||
Temperature apijson.Field
|
||||
Tools apijson.Field
|
||||
@@ -730,16 +1090,134 @@ func (r ConfigModeBuildMode) IsKnown() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigModeBuildPermission struct {
|
||||
Bash ConfigModeBuildPermissionBashUnion `json:"bash"`
|
||||
Edit ConfigModeBuildPermissionEdit `json:"edit"`
|
||||
Webfetch ConfigModeBuildPermissionWebfetch `json:"webfetch"`
|
||||
JSON configModeBuildPermissionJSON `json:"-"`
|
||||
}
|
||||
|
||||
// configModeBuildPermissionJSON contains the JSON metadata for the struct
|
||||
// [ConfigModeBuildPermission]
|
||||
type configModeBuildPermissionJSON struct {
|
||||
Bash apijson.Field
|
||||
Edit apijson.Field
|
||||
Webfetch apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *ConfigModeBuildPermission) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r configModeBuildPermissionJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
// Union satisfied by [ConfigModeBuildPermissionBashString] or
|
||||
// [ConfigModeBuildPermissionBashMap].
|
||||
type ConfigModeBuildPermissionBashUnion interface {
|
||||
implementsConfigModeBuildPermissionBashUnion()
|
||||
}
|
||||
|
||||
func init() {
|
||||
apijson.RegisterUnion(
|
||||
reflect.TypeOf((*ConfigModeBuildPermissionBashUnion)(nil)).Elem(),
|
||||
"",
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.String,
|
||||
Type: reflect.TypeOf(ConfigModeBuildPermissionBashString("")),
|
||||
},
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.JSON,
|
||||
Type: reflect.TypeOf(ConfigModeBuildPermissionBashMap{}),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type ConfigModeBuildPermissionBashString string
|
||||
|
||||
const (
|
||||
ConfigModeBuildPermissionBashStringAsk ConfigModeBuildPermissionBashString = "ask"
|
||||
ConfigModeBuildPermissionBashStringAllow ConfigModeBuildPermissionBashString = "allow"
|
||||
ConfigModeBuildPermissionBashStringDeny ConfigModeBuildPermissionBashString = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModeBuildPermissionBashString) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModeBuildPermissionBashStringAsk, ConfigModeBuildPermissionBashStringAllow, ConfigModeBuildPermissionBashStringDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r ConfigModeBuildPermissionBashString) implementsConfigModeBuildPermissionBashUnion() {}
|
||||
|
||||
type ConfigModeBuildPermissionBashMap map[string]ConfigModeBuildPermissionBashMapItem
|
||||
|
||||
func (r ConfigModeBuildPermissionBashMap) implementsConfigModeBuildPermissionBashUnion() {}
|
||||
|
||||
type ConfigModeBuildPermissionBashMapItem string
|
||||
|
||||
const (
|
||||
ConfigModeBuildPermissionBashMapAsk ConfigModeBuildPermissionBashMapItem = "ask"
|
||||
ConfigModeBuildPermissionBashMapAllow ConfigModeBuildPermissionBashMapItem = "allow"
|
||||
ConfigModeBuildPermissionBashMapDeny ConfigModeBuildPermissionBashMapItem = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModeBuildPermissionBashMapItem) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModeBuildPermissionBashMapAsk, ConfigModeBuildPermissionBashMapAllow, ConfigModeBuildPermissionBashMapDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigModeBuildPermissionEdit string
|
||||
|
||||
const (
|
||||
ConfigModeBuildPermissionEditAsk ConfigModeBuildPermissionEdit = "ask"
|
||||
ConfigModeBuildPermissionEditAllow ConfigModeBuildPermissionEdit = "allow"
|
||||
ConfigModeBuildPermissionEditDeny ConfigModeBuildPermissionEdit = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModeBuildPermissionEdit) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModeBuildPermissionEditAsk, ConfigModeBuildPermissionEditAllow, ConfigModeBuildPermissionEditDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigModeBuildPermissionWebfetch string
|
||||
|
||||
const (
|
||||
ConfigModeBuildPermissionWebfetchAsk ConfigModeBuildPermissionWebfetch = "ask"
|
||||
ConfigModeBuildPermissionWebfetchAllow ConfigModeBuildPermissionWebfetch = "allow"
|
||||
ConfigModeBuildPermissionWebfetchDeny ConfigModeBuildPermissionWebfetch = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModeBuildPermissionWebfetch) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModeBuildPermissionWebfetchAsk, ConfigModeBuildPermissionWebfetchAllow, ConfigModeBuildPermissionWebfetchDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigModePlan struct {
|
||||
// Description of when to use the agent
|
||||
Description string `json:"description"`
|
||||
Disable bool `json:"disable"`
|
||||
Mode ConfigModePlanMode `json:"mode"`
|
||||
Model string `json:"model"`
|
||||
Permission ConfigModePlanPermission `json:"permission"`
|
||||
Prompt string `json:"prompt"`
|
||||
Temperature float64 `json:"temperature"`
|
||||
Tools map[string]bool `json:"tools"`
|
||||
TopP float64 `json:"top_p"`
|
||||
ExtraFields map[string]interface{} `json:"-,extras"`
|
||||
JSON configModePlanJSON `json:"-"`
|
||||
}
|
||||
|
||||
@@ -749,6 +1227,7 @@ type configModePlanJSON struct {
|
||||
Disable apijson.Field
|
||||
Mode apijson.Field
|
||||
Model apijson.Field
|
||||
Permission apijson.Field
|
||||
Prompt apijson.Field
|
||||
Temperature apijson.Field
|
||||
Tools apijson.Field
|
||||
@@ -781,6 +1260,122 @@ func (r ConfigModePlanMode) IsKnown() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigModePlanPermission struct {
|
||||
Bash ConfigModePlanPermissionBashUnion `json:"bash"`
|
||||
Edit ConfigModePlanPermissionEdit `json:"edit"`
|
||||
Webfetch ConfigModePlanPermissionWebfetch `json:"webfetch"`
|
||||
JSON configModePlanPermissionJSON `json:"-"`
|
||||
}
|
||||
|
||||
// configModePlanPermissionJSON contains the JSON metadata for the struct
|
||||
// [ConfigModePlanPermission]
|
||||
type configModePlanPermissionJSON struct {
|
||||
Bash apijson.Field
|
||||
Edit apijson.Field
|
||||
Webfetch apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
|
||||
func (r *ConfigModePlanPermission) UnmarshalJSON(data []byte) (err error) {
|
||||
return apijson.UnmarshalRoot(data, r)
|
||||
}
|
||||
|
||||
func (r configModePlanPermissionJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
// Union satisfied by [ConfigModePlanPermissionBashString] or
|
||||
// [ConfigModePlanPermissionBashMap].
|
||||
type ConfigModePlanPermissionBashUnion interface {
|
||||
implementsConfigModePlanPermissionBashUnion()
|
||||
}
|
||||
|
||||
func init() {
|
||||
apijson.RegisterUnion(
|
||||
reflect.TypeOf((*ConfigModePlanPermissionBashUnion)(nil)).Elem(),
|
||||
"",
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.String,
|
||||
Type: reflect.TypeOf(ConfigModePlanPermissionBashString("")),
|
||||
},
|
||||
apijson.UnionVariant{
|
||||
TypeFilter: gjson.JSON,
|
||||
Type: reflect.TypeOf(ConfigModePlanPermissionBashMap{}),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type ConfigModePlanPermissionBashString string
|
||||
|
||||
const (
|
||||
ConfigModePlanPermissionBashStringAsk ConfigModePlanPermissionBashString = "ask"
|
||||
ConfigModePlanPermissionBashStringAllow ConfigModePlanPermissionBashString = "allow"
|
||||
ConfigModePlanPermissionBashStringDeny ConfigModePlanPermissionBashString = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModePlanPermissionBashString) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModePlanPermissionBashStringAsk, ConfigModePlanPermissionBashStringAllow, ConfigModePlanPermissionBashStringDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r ConfigModePlanPermissionBashString) implementsConfigModePlanPermissionBashUnion() {}
|
||||
|
||||
type ConfigModePlanPermissionBashMap map[string]ConfigModePlanPermissionBashMapItem
|
||||
|
||||
func (r ConfigModePlanPermissionBashMap) implementsConfigModePlanPermissionBashUnion() {}
|
||||
|
||||
type ConfigModePlanPermissionBashMapItem string
|
||||
|
||||
const (
|
||||
ConfigModePlanPermissionBashMapAsk ConfigModePlanPermissionBashMapItem = "ask"
|
||||
ConfigModePlanPermissionBashMapAllow ConfigModePlanPermissionBashMapItem = "allow"
|
||||
ConfigModePlanPermissionBashMapDeny ConfigModePlanPermissionBashMapItem = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModePlanPermissionBashMapItem) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModePlanPermissionBashMapAsk, ConfigModePlanPermissionBashMapAllow, ConfigModePlanPermissionBashMapDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigModePlanPermissionEdit string
|
||||
|
||||
const (
|
||||
ConfigModePlanPermissionEditAsk ConfigModePlanPermissionEdit = "ask"
|
||||
ConfigModePlanPermissionEditAllow ConfigModePlanPermissionEdit = "allow"
|
||||
ConfigModePlanPermissionEditDeny ConfigModePlanPermissionEdit = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModePlanPermissionEdit) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModePlanPermissionEditAsk, ConfigModePlanPermissionEditAllow, ConfigModePlanPermissionEditDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigModePlanPermissionWebfetch string
|
||||
|
||||
const (
|
||||
ConfigModePlanPermissionWebfetchAsk ConfigModePlanPermissionWebfetch = "ask"
|
||||
ConfigModePlanPermissionWebfetchAllow ConfigModePlanPermissionWebfetch = "allow"
|
||||
ConfigModePlanPermissionWebfetchDeny ConfigModePlanPermissionWebfetch = "deny"
|
||||
)
|
||||
|
||||
func (r ConfigModePlanPermissionWebfetch) IsKnown() bool {
|
||||
switch r {
|
||||
case ConfigModePlanPermissionWebfetchAsk, ConfigModePlanPermissionWebfetchAllow, ConfigModePlanPermissionWebfetchDeny:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ConfigPermission struct {
|
||||
Bash ConfigPermissionBashUnion `json:"bash"`
|
||||
Edit ConfigPermissionEdit `json:"edit"`
|
||||
@@ -897,10 +1492,10 @@ func (r ConfigPermissionWebfetch) IsKnown() bool {
|
||||
}
|
||||
|
||||
type ConfigProvider struct {
|
||||
Models map[string]ConfigProviderModel `json:"models,required"`
|
||||
ID string `json:"id"`
|
||||
API string `json:"api"`
|
||||
Env []string `json:"env"`
|
||||
Models map[string]ConfigProviderModel `json:"models"`
|
||||
Name string `json:"name"`
|
||||
Npm string `json:"npm"`
|
||||
Options ConfigProviderOptions `json:"options"`
|
||||
@@ -909,10 +1504,10 @@ type ConfigProvider struct {
|
||||
|
||||
// configProviderJSON contains the JSON metadata for the struct [ConfigProvider]
|
||||
type configProviderJSON struct {
|
||||
Models apijson.Field
|
||||
ID apijson.Field
|
||||
API apijson.Field
|
||||
Env apijson.Field
|
||||
Models apijson.Field
|
||||
Name apijson.Field
|
||||
Npm apijson.Field
|
||||
Options apijson.Field
|
||||
@@ -1138,6 +1733,8 @@ type KeybindsConfig struct {
|
||||
SwitchModeReverse string `json:"switch_mode_reverse,required"`
|
||||
// List available themes
|
||||
ThemeList string `json:"theme_list,required"`
|
||||
// Toggle thinking blocks
|
||||
ThinkingBlocks string `json:"thinking_blocks,required"`
|
||||
// Toggle tool details
|
||||
ToolDetails string `json:"tool_details,required"`
|
||||
JSON keybindsConfigJSON `json:"-"`
|
||||
@@ -1184,6 +1781,7 @@ type keybindsConfigJSON struct {
|
||||
SwitchMode apijson.Field
|
||||
SwitchModeReverse apijson.Field
|
||||
ThemeList apijson.Field
|
||||
ThinkingBlocks apijson.Field
|
||||
ToolDetails apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
|
||||
@@ -46,6 +46,18 @@ func (r *SessionService) New(ctx context.Context, opts ...option.RequestOption)
|
||||
return
|
||||
}
|
||||
|
||||
// Update session properties
|
||||
func (r *SessionService) Update(ctx context.Context, id string, body SessionUpdateParams, opts ...option.RequestOption) (res *Session, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
if id == "" {
|
||||
err = errors.New("missing required id parameter")
|
||||
return
|
||||
}
|
||||
path := fmt.Sprintf("session/%s", id)
|
||||
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...)
|
||||
return
|
||||
}
|
||||
|
||||
// List all sessions
|
||||
func (r *SessionService) List(ctx context.Context, opts ...option.RequestOption) (res *[]Session, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
@@ -66,18 +78,6 @@ func (r *SessionService) Delete(ctx context.Context, id string, opts ...option.R
|
||||
return
|
||||
}
|
||||
|
||||
// Update session properties
|
||||
func (r *SessionService) Update(ctx context.Context, id string, body SessionUpdateParams, opts ...option.RequestOption) (res *Session, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
if id == "" {
|
||||
err = errors.New("missing required id parameter")
|
||||
return
|
||||
}
|
||||
path := fmt.Sprintf("session/%s", id)
|
||||
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...)
|
||||
return
|
||||
}
|
||||
|
||||
// Abort a session
|
||||
func (r *SessionService) Abort(ctx context.Context, id string, opts ...option.RequestOption) (res *bool, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
@@ -90,6 +90,18 @@ func (r *SessionService) Abort(ctx context.Context, id string, opts ...option.Re
|
||||
return
|
||||
}
|
||||
|
||||
// Run a bash command
|
||||
func (r *SessionService) Bash(ctx context.Context, id string, body SessionBashParams, opts ...option.RequestOption) (res *AssistantMessage, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
if id == "" {
|
||||
err = errors.New("missing required id parameter")
|
||||
return
|
||||
}
|
||||
path := fmt.Sprintf("session/%s/bash", id)
|
||||
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
|
||||
return
|
||||
}
|
||||
|
||||
// Create and send a new message to a session
|
||||
func (r *SessionService) Chat(ctx context.Context, id string, body SessionChatParams, opts ...option.RequestOption) (res *AssistantMessage, err error) {
|
||||
opts = append(r.Options[:], opts...)
|
||||
@@ -976,10 +988,10 @@ type Part struct {
|
||||
// This field can have the runtime type of [[]string].
|
||||
Files interface{} `json:"files"`
|
||||
Hash string `json:"hash"`
|
||||
// This field can have the runtime type of [map[string]interface{}].
|
||||
Metadata interface{} `json:"metadata"`
|
||||
Mime string `json:"mime"`
|
||||
Name string `json:"name"`
|
||||
// This field can have the runtime type of [map[string]interface{}].
|
||||
ProviderMetadata interface{} `json:"providerMetadata"`
|
||||
Snapshot string `json:"snapshot"`
|
||||
// This field can have the runtime type of [FilePartSource], [AgentPartSource].
|
||||
Source interface{} `json:"source"`
|
||||
@@ -1008,9 +1020,9 @@ type partJSON struct {
|
||||
Filename apijson.Field
|
||||
Files apijson.Field
|
||||
Hash apijson.Field
|
||||
Metadata apijson.Field
|
||||
Mime apijson.Field
|
||||
Name apijson.Field
|
||||
ProviderMetadata apijson.Field
|
||||
Snapshot apijson.Field
|
||||
Source apijson.Field
|
||||
State apijson.Field
|
||||
@@ -1179,9 +1191,9 @@ type ReasoningPart struct {
|
||||
MessageID string `json:"messageID,required"`
|
||||
SessionID string `json:"sessionID,required"`
|
||||
Text string `json:"text,required"`
|
||||
Time ReasoningPartTime `json:"time,required"`
|
||||
Type ReasoningPartType `json:"type,required"`
|
||||
ProviderMetadata map[string]interface{} `json:"providerMetadata"`
|
||||
Time ReasoningPartTime `json:"time"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
JSON reasoningPartJSON `json:"-"`
|
||||
}
|
||||
|
||||
@@ -1191,9 +1203,9 @@ type reasoningPartJSON struct {
|
||||
MessageID apijson.Field
|
||||
SessionID apijson.Field
|
||||
Text apijson.Field
|
||||
Type apijson.Field
|
||||
ProviderMetadata apijson.Field
|
||||
Time apijson.Field
|
||||
Type apijson.Field
|
||||
Metadata apijson.Field
|
||||
raw string
|
||||
ExtraFields map[string]apijson.Field
|
||||
}
|
||||
@@ -1208,20 +1220,6 @@ func (r reasoningPartJSON) RawJSON() string {
|
||||
|
||||
func (r ReasoningPart) implementsPart() {}
|
||||
|
||||
type ReasoningPartType string
|
||||
|
||||
const (
|
||||
ReasoningPartTypeReasoning ReasoningPartType = "reasoning"
|
||||
)
|
||||
|
||||
func (r ReasoningPartType) IsKnown() bool {
|
||||
switch r {
|
||||
case ReasoningPartTypeReasoning:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ReasoningPartTime struct {
|
||||
Start float64 `json:"start,required"`
|
||||
End float64 `json:"end"`
|
||||
@@ -1245,6 +1243,20 @@ func (r reasoningPartTimeJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
type ReasoningPartType string
|
||||
|
||||
const (
|
||||
ReasoningPartTypeReasoning ReasoningPartType = "reasoning"
|
||||
)
|
||||
|
||||
func (r ReasoningPartType) IsKnown() bool {
|
||||
switch r {
|
||||
case ReasoningPartTypeReasoning:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
ID string `json:"id,required"`
|
||||
Time SessionTime `json:"time,required"`
|
||||
@@ -2286,6 +2298,23 @@ func (r sessionMessagesResponseJSON) RawJSON() string {
|
||||
return r.raw
|
||||
}
|
||||
|
||||
type SessionUpdateParams struct {
|
||||
Title param.Field[string] `json:"title"`
|
||||
}
|
||||
|
||||
func (r SessionUpdateParams) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
type SessionBashParams struct {
|
||||
Agent param.Field[string] `json:"agent,required"`
|
||||
Command param.Field[string] `json:"command,required"`
|
||||
}
|
||||
|
||||
func (r SessionBashParams) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
type SessionChatParams struct {
|
||||
ModelID param.Field[string] `json:"modelID,required"`
|
||||
Parts param.Field[[]SessionChatParamsPartUnion] `json:"parts,required"`
|
||||
@@ -2368,11 +2397,3 @@ type SessionSummarizeParams struct {
|
||||
func (r SessionSummarizeParams) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
type SessionUpdateParams struct {
|
||||
Title param.Field[string] `json:"title"`
|
||||
}
|
||||
|
||||
func (r SessionUpdateParams) MarshalJSON() (data []byte, err error) {
|
||||
return apijson.MarshalRoot(r)
|
||||
}
|
||||
|
||||
@@ -35,6 +35,34 @@ func TestSessionNew(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionUpdateWithOptionalParams(t *testing.T) {
|
||||
t.Skip("skipped: tests are disabled for the time being")
|
||||
baseURL := "http://localhost:4010"
|
||||
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
|
||||
baseURL = envURL
|
||||
}
|
||||
if !testutil.CheckTestServer(t, baseURL) {
|
||||
return
|
||||
}
|
||||
client := opencode.NewClient(
|
||||
option.WithBaseURL(baseURL),
|
||||
)
|
||||
_, err := client.Session.Update(
|
||||
context.TODO(),
|
||||
"id",
|
||||
opencode.SessionUpdateParams{
|
||||
Title: opencode.F("title"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
var apierr *opencode.Error
|
||||
if errors.As(err, &apierr) {
|
||||
t.Log(string(apierr.DumpRequest(true)))
|
||||
}
|
||||
t.Fatalf("err should be nil: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionList(t *testing.T) {
|
||||
t.Skip("skipped: tests are disabled for the time being")
|
||||
baseURL := "http://localhost:4010"
|
||||
@@ -101,6 +129,35 @@ func TestSessionAbort(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionBash(t *testing.T) {
|
||||
t.Skip("skipped: tests are disabled for the time being")
|
||||
baseURL := "http://localhost:4010"
|
||||
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
|
||||
baseURL = envURL
|
||||
}
|
||||
if !testutil.CheckTestServer(t, baseURL) {
|
||||
return
|
||||
}
|
||||
client := opencode.NewClient(
|
||||
option.WithBaseURL(baseURL),
|
||||
)
|
||||
_, err := client.Session.Bash(
|
||||
context.TODO(),
|
||||
"id",
|
||||
opencode.SessionBashParams{
|
||||
Agent: opencode.F("agent"),
|
||||
Command: opencode.F("command"),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
var apierr *opencode.Error
|
||||
if errors.As(err, &apierr) {
|
||||
t.Log(string(apierr.DumpRequest(true)))
|
||||
}
|
||||
t.Fatalf("err should be nil: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionChatWithOptionalParams(t *testing.T) {
|
||||
t.Skip("skipped: tests are disabled for the time being")
|
||||
baseURL := "http://localhost:4010"
|
||||
|
||||
@@ -124,6 +124,8 @@ resources:
|
||||
message: get /session/{id}/message/{messageID}
|
||||
messages: get /session/{id}/message
|
||||
chat: post /session/{id}/message
|
||||
bash: post /session/{id}/bash
|
||||
update: patch /session/{id}
|
||||
revert: post /session/{id}/revert
|
||||
unrevert: post /session/{id}/unrevert
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ type App struct {
|
||||
InitialSession *string
|
||||
compactCancel context.CancelFunc
|
||||
IsLeaderSequence bool
|
||||
IsBashMode bool
|
||||
}
|
||||
|
||||
func (a *App) Agent() *opencode.Agent {
|
||||
@@ -79,6 +80,9 @@ type AgentSelectedMsg struct {
|
||||
type SessionClearedMsg struct{}
|
||||
type CompactSessionMsg struct{}
|
||||
type SendPrompt = Prompt
|
||||
type SendBash = struct {
|
||||
Command string
|
||||
}
|
||||
type SetEditorContentMsg struct {
|
||||
Text string
|
||||
}
|
||||
@@ -296,23 +300,41 @@ func (a *App) CycleRecentModel() (*App, tea.Cmd) {
|
||||
}
|
||||
nextIndex := 0
|
||||
for i, recentModel := range recentModels {
|
||||
if a.Provider != nil && a.Model != nil && recentModel.ProviderID == a.Provider.ID && recentModel.ModelID == a.Model.ID {
|
||||
if a.Provider != nil && a.Model != nil && recentModel.ProviderID == a.Provider.ID &&
|
||||
recentModel.ModelID == a.Model.ID {
|
||||
nextIndex = (i + 1) % len(recentModels)
|
||||
break
|
||||
}
|
||||
}
|
||||
for range recentModels {
|
||||
currentRecentModel := recentModels[nextIndex%len(recentModels)]
|
||||
provider, model := findModelByProviderAndModelID(a.Providers, currentRecentModel.ProviderID, currentRecentModel.ModelID)
|
||||
provider, model := findModelByProviderAndModelID(
|
||||
a.Providers,
|
||||
currentRecentModel.ProviderID,
|
||||
currentRecentModel.ModelID,
|
||||
)
|
||||
if provider != nil && model != nil {
|
||||
a.Provider, a.Model = provider, model
|
||||
a.State.AgentModel[a.Agent().Name] = AgentModel{ProviderID: provider.ID, ModelID: model.ID}
|
||||
return a, tea.Sequence(a.SaveState(), toast.NewSuccessToast(fmt.Sprintf("Switched to %s (%s)", model.Name, provider.Name)))
|
||||
a.State.AgentModel[a.Agent().Name] = AgentModel{
|
||||
ProviderID: provider.ID,
|
||||
ModelID: model.ID,
|
||||
}
|
||||
recentModels = append(recentModels[:nextIndex%len(recentModels)], recentModels[nextIndex%len(recentModels)+1:]...)
|
||||
return a, tea.Sequence(
|
||||
a.SaveState(),
|
||||
toast.NewSuccessToast(
|
||||
fmt.Sprintf("Switched to %s (%s)", model.Name, provider.Name),
|
||||
),
|
||||
)
|
||||
}
|
||||
recentModels = append(
|
||||
recentModels[:nextIndex%len(recentModels)],
|
||||
recentModels[nextIndex%len(recentModels)+1:]...)
|
||||
if len(recentModels) < 2 {
|
||||
a.State.RecentlyUsedModels = recentModels
|
||||
return a, tea.Sequence(a.SaveState(), toast.NewInfoToast("Not enough valid recent models to cycle"))
|
||||
return a, tea.Sequence(
|
||||
a.SaveState(),
|
||||
toast.NewInfoToast("Not enough valid recent models to cycle"),
|
||||
)
|
||||
}
|
||||
}
|
||||
a.State.RecentlyUsedModels = recentModels
|
||||
@@ -464,10 +486,19 @@ func (a *App) InitializeProvider() tea.Cmd {
|
||||
|
||||
// Priority 3: Current agent's preferred model
|
||||
if selectedProvider == nil && a.Agent().Model.ModelID != "" {
|
||||
if provider, model := findModelByProviderAndModelID(providers, a.Agent().Model.ProviderID, a.Agent().Model.ModelID); provider != nil && model != nil {
|
||||
if provider, model := findModelByProviderAndModelID(providers, a.Agent().Model.ProviderID, a.Agent().Model.ModelID); provider != nil &&
|
||||
model != nil {
|
||||
selectedProvider = provider
|
||||
selectedModel = model
|
||||
slog.Debug("Selected model from current agent", "provider", provider.ID, "model", model.ID, "agent", a.Agent().Name)
|
||||
slog.Debug(
|
||||
"Selected model from current agent",
|
||||
"provider",
|
||||
provider.ID,
|
||||
"model",
|
||||
model.ID,
|
||||
"agent",
|
||||
a.Agent().Name,
|
||||
)
|
||||
} else {
|
||||
slog.Debug("Agent model not found", "provider", a.Agent().Model.ProviderID, "model", a.Agent().Model.ModelID, "agent", a.Agent().Name)
|
||||
}
|
||||
@@ -724,6 +755,38 @@ func (a *App) SendPrompt(ctx context.Context, prompt Prompt) (*App, tea.Cmd) {
|
||||
return a, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (a *App) SendBash(ctx context.Context, command string) (*App, tea.Cmd) {
|
||||
var cmds []tea.Cmd
|
||||
if a.Session.ID == "" {
|
||||
session, err := a.CreateSession(ctx)
|
||||
if err != nil {
|
||||
return a, toast.NewErrorToast(err.Error())
|
||||
}
|
||||
a.Session = session
|
||||
cmds = append(cmds, util.CmdHandler(SessionCreatedMsg{Session: session}))
|
||||
}
|
||||
|
||||
cmds = append(cmds, func() tea.Msg {
|
||||
_, err := a.Client.Session.Bash(
|
||||
context.Background(),
|
||||
a.Session.ID,
|
||||
opencode.SessionBashParams{
|
||||
Agent: opencode.F(a.Agent().Name),
|
||||
Command: opencode.F(command),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
slog.Error("Failed to submit bash command", "error", err)
|
||||
return toast.NewErrorToast("Failed to submit bash command")()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// The actual response will come through SSE
|
||||
// For now, just return success
|
||||
return a, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (a *App) Cancel(ctx context.Context, sessionID string) error {
|
||||
// Cancel any running compact operation
|
||||
if a.compactCancel != nil {
|
||||
|
||||
@@ -39,6 +39,7 @@ type EditorComponent interface {
|
||||
Focus() (tea.Model, tea.Cmd)
|
||||
Blur()
|
||||
Submit() (tea.Model, tea.Cmd)
|
||||
SubmitBash() (tea.Model, tea.Cmd)
|
||||
Clear() (tea.Model, tea.Cmd)
|
||||
Paste() (tea.Model, tea.Cmd)
|
||||
Newline() (tea.Model, tea.Cmd)
|
||||
@@ -342,6 +343,14 @@ func (m *editorComponent) Content() string {
|
||||
Padding(0, 0, 0, 1).
|
||||
Bold(true)
|
||||
prompt := promptStyle.Render(">")
|
||||
borderForeground := t.Border()
|
||||
if m.app.IsLeaderSequence {
|
||||
borderForeground = t.Accent()
|
||||
}
|
||||
if m.app.IsBashMode {
|
||||
borderForeground = t.Secondary()
|
||||
prompt = promptStyle.Render("!")
|
||||
}
|
||||
|
||||
m.textarea.SetWidth(width - 6)
|
||||
textarea := lipgloss.JoinHorizontal(
|
||||
@@ -349,10 +358,6 @@ func (m *editorComponent) Content() string {
|
||||
prompt,
|
||||
m.textarea.View(),
|
||||
)
|
||||
borderForeground := t.Border()
|
||||
if m.app.IsLeaderSequence {
|
||||
borderForeground = t.Accent()
|
||||
}
|
||||
textarea = styles.NewStyle().
|
||||
Background(t.BackgroundElement()).
|
||||
Width(width).
|
||||
@@ -489,6 +494,16 @@ func (m *editorComponent) Submit() (tea.Model, tea.Cmd) {
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m *editorComponent) SubmitBash() (tea.Model, tea.Cmd) {
|
||||
command := m.textarea.Value()
|
||||
var cmds []tea.Cmd
|
||||
updated, cmd := m.Clear()
|
||||
m = updated.(*editorComponent)
|
||||
cmds = append(cmds, cmd)
|
||||
cmds = append(cmds, util.CmdHandler(app.SendBash{Command: command}))
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m *editorComponent) Clear() (tea.Model, tea.Cmd) {
|
||||
m.textarea.Reset()
|
||||
m.historyIndex = -1
|
||||
|
||||
@@ -151,6 +151,23 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
if a.app.IsBashMode {
|
||||
if keyString == "backspace" && a.editor.Length() == 0 {
|
||||
a.app.IsBashMode = false
|
||||
return a, nil
|
||||
}
|
||||
|
||||
if keyString == "enter" || keyString == "esc" || keyString == "ctrl+c" {
|
||||
a.app.IsBashMode = false
|
||||
if keyString == "enter" {
|
||||
updated, cmd := a.editor.SubmitBash()
|
||||
a.editor = updated.(chat.EditorComponent)
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
return a, tea.Batch(cmds...)
|
||||
}
|
||||
}
|
||||
|
||||
// 1. Handle active modal
|
||||
if a.modal != nil {
|
||||
switch keyString {
|
||||
@@ -189,7 +206,8 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
// 3. Handle completions trigger
|
||||
if keyString == "/" &&
|
||||
!a.showCompletionDialog &&
|
||||
a.editor.Value() == "" {
|
||||
a.editor.Value() == "" &&
|
||||
!a.app.IsBashMode {
|
||||
a.showCompletionDialog = true
|
||||
|
||||
updated, cmd := a.editor.Update(msg)
|
||||
@@ -207,7 +225,8 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
|
||||
// Handle file completions trigger
|
||||
if keyString == "@" &&
|
||||
!a.showCompletionDialog {
|
||||
!a.showCompletionDialog &&
|
||||
!a.app.IsBashMode {
|
||||
a.showCompletionDialog = true
|
||||
|
||||
updated, cmd := a.editor.Update(msg)
|
||||
@@ -223,6 +242,11 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return a, tea.Sequence(cmds...)
|
||||
}
|
||||
|
||||
if keyString == "!" && a.editor.Value() == "" {
|
||||
a.app.IsBashMode = true
|
||||
return a, nil
|
||||
}
|
||||
|
||||
if a.showCompletionDialog {
|
||||
switch keyString {
|
||||
case "tab", "enter", "esc", "ctrl+c", "up", "down", "ctrl+p", "ctrl+n":
|
||||
@@ -378,6 +402,9 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
a.showCompletionDialog = false
|
||||
a.app, cmd = a.app.SendPrompt(context.Background(), msg)
|
||||
cmds = append(cmds, cmd)
|
||||
case app.SendBash:
|
||||
a.app, cmd = a.app.SendBash(context.Background(), msg.Command)
|
||||
cmds = append(cmds, cmd)
|
||||
case app.SetEditorContentMsg:
|
||||
// Set the editor content without sending
|
||||
a.editor.SetValueWithAttachments(msg.Text)
|
||||
|
||||
Reference in New Issue
Block a user