summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdotdevin <[email protected]>2025-08-13 13:28:22 -0500
committeradamdotdevin <[email protected]>2025-08-13 13:28:22 -0500
commit1357319f6f01532a3544a23d9282f9583a422608 (patch)
tree1336779e02fea755bc45c8fc6d8f6db6ccbb9ccc
parente729eed34d54758d4630012bf2396c064a71522e (diff)
downloadopencode-1357319f6f01532a3544a23d9282f9583a422608.tar.gz
opencode-1357319f6f01532a3544a23d9282f9583a422608.zip
feat: bash commands
-rw-r--r--packages/opencode/src/session/index.ts9
-rw-r--r--packages/sdk/go/.stats.yml8
-rw-r--r--packages/sdk/go/api.md2
-rw-r--r--packages/sdk/go/app.go94
-rw-r--r--packages/sdk/go/config.go692
-rw-r--r--packages/sdk/go/session.go169
-rw-r--r--packages/sdk/go/session_test.go57
-rw-r--r--packages/sdk/stainless/stainless.yml2
-rw-r--r--packages/tui/internal/app/app.go79
-rw-r--r--packages/tui/internal/components/chat/editor.go23
-rw-r--r--packages/tui/internal/tui/tui.go31
11 files changed, 1014 insertions, 152 deletions
diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts
index c1cf034d2..a6c536b7d 100644
--- a/packages/opencode/src/session/index.ts
+++ b/packages/opencode/src/session/index.ts
@@ -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()
})
})
diff --git a/packages/sdk/go/.stats.yml b/packages/sdk/go/.stats.yml
index 4db6fb4c0..d9ba9daf4 100644
--- a/packages/sdk/go/.stats.yml
+++ b/packages/sdk/go/.stats.yml
@@ -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
diff --git a/packages/sdk/go/api.md b/packages/sdk/go/api.md
index eeef10331..5f2bc310d 100644
--- a/packages/sdk/go/api.md
+++ b/packages/sdk/go/api.md
@@ -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>
diff --git a/packages/sdk/go/app.go b/packages/sdk/go/app.go
index 3a0161a16..2771f6bd4 100644
--- a/packages/sdk/go/app.go
+++ b/packages/sdk/go/app.go
@@ -72,21 +72,25 @@ func (r *AppService) Providers(ctx context.Context, opts ...option.RequestOption
}
type Agent struct {
- Mode AgentMode `json:"mode,required"`
- Name string `json:"name,required"`
- Tools map[string]bool `json:"tools,required"`
- Description string `json:"description"`
- Model AgentModel `json:"model"`
- Prompt string `json:"prompt"`
- Temperature float64 `json:"temperature"`
- TopP float64 `json:"topP"`
- JSON agentJSON `json:"-"`
+ 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"`
+ Prompt string `json:"prompt"`
+ Temperature float64 `json:"temperature"`
+ TopP float64 `json:"topP"`
+ JSON agentJSON `json:"-"`
}
// agentJSON contains the JSON metadata for the struct [Agent]
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"`
diff --git a/packages/sdk/go/config.go b/packages/sdk/go/config.go
index ed3e3c5ab..47d2fa580 100644
--- a/packages/sdk/go/config.go
+++ b/packages/sdk/go/config.go
@@ -149,15 +149,17 @@ func (r configAgentJSON) RawJSON() string {
type ConfigAgentBuild struct {
// Description of when to use the agent
- Description string `json:"description"`
- Disable bool `json:"disable"`
- Mode ConfigAgentBuildMode `json:"mode"`
- Model string `json:"model"`
- Prompt string `json:"prompt"`
- Temperature float64 `json:"temperature"`
- Tools map[string]bool `json:"tools"`
- TopP float64 `json:"top_p"`
- JSON configAgentBuildJSON `json:"-"`
+ Description string `json:"description"`
+ 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:"-"`
}
// configAgentBuildJSON contains the JSON metadata for the struct
@@ -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,17 +202,135 @@ 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"`
- Prompt string `json:"prompt"`
- Temperature float64 `json:"temperature"`
- Tools map[string]bool `json:"tools"`
- TopP float64 `json:"top_p"`
- JSON configAgentGeneralJSON `json:"-"`
+ 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:"-"`
}
// configAgentGeneralJSON contains the JSON metadata for the struct
@@ -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,17 +373,135 @@ 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"`
- Prompt string `json:"prompt"`
- Temperature float64 `json:"temperature"`
- Tools map[string]bool `json:"tools"`
- TopP float64 `json:"top_p"`
- JSON configAgentPlanJSON `json:"-"`
+ 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:"-"`
}
// configAgentPlanJSON contains the JSON metadata for the struct [ConfigAgentPlan]
@@ -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:"-"`
@@ -681,15 +1038,17 @@ func (r configModeJSON) RawJSON() string {
type ConfigModeBuild struct {
// Description of when to use the agent
- Description string `json:"description"`
- Disable bool `json:"disable"`
- Mode ConfigModeBuildMode `json:"mode"`
- Model string `json:"model"`
- Prompt string `json:"prompt"`
- Temperature float64 `json:"temperature"`
- Tools map[string]bool `json:"tools"`
- TopP float64 `json:"top_p"`
- JSON configModeBuildJSON `json:"-"`
+ Description string `json:"description"`
+ 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:"-"`
}
// configModeBuildJSON contains the JSON metadata for the struct [ConfigModeBuild]
@@ -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,17 +1090,135 @@ 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"`
- Prompt string `json:"prompt"`
- Temperature float64 `json:"temperature"`
- Tools map[string]bool `json:"tools"`
- TopP float64 `json:"top_p"`
- JSON configModePlanJSON `json:"-"`
+ 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:"-"`
}
// configModePlanJSON contains the JSON metadata for the struct [ConfigModePlan]
@@ -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
diff --git a/packages/sdk/go/session.go b/packages/sdk/go/session.go
index f377b2e4e..b8c156b6b 100644
--- a/packages/sdk/go/session.go
+++ b/packages/sdk/go/session.go
@@ -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,27 +78,27 @@ 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) {
+// Abort a session
+func (r *SessionService) Abort(ctx context.Context, id string, opts ...option.RequestOption) (res *bool, 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...)
+ path := fmt.Sprintf("session/%s/abort", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
return
}
-// Abort a session
-func (r *SessionService) Abort(ctx context.Context, id string, opts ...option.RequestOption) (res *bool, err error) {
+// 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/abort", id)
- err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ path := fmt.Sprintf("session/%s/bash", id)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
return
}
@@ -976,11 +988,11 @@ type Part struct {
// This field can have the runtime type of [[]string].
Files interface{} `json:"files"`
Hash string `json:"hash"`
- 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"`
+ Metadata interface{} `json:"metadata"`
+ Mime string `json:"mime"`
+ Name string `json:"name"`
+ Snapshot string `json:"snapshot"`
// This field can have the runtime type of [FilePartSource], [AgentPartSource].
Source interface{} `json:"source"`
// This field can have the runtime type of [ToolPartState].
@@ -999,29 +1011,29 @@ type Part struct {
// partJSON contains the JSON metadata for the struct [Part]
type partJSON struct {
- ID apijson.Field
- MessageID apijson.Field
- SessionID apijson.Field
- Type apijson.Field
- CallID apijson.Field
- Cost apijson.Field
- Filename apijson.Field
- Files apijson.Field
- Hash apijson.Field
- Mime apijson.Field
- Name apijson.Field
- ProviderMetadata apijson.Field
- Snapshot apijson.Field
- Source apijson.Field
- State apijson.Field
- Synthetic apijson.Field
- Text apijson.Field
- Time apijson.Field
- Tokens apijson.Field
- Tool apijson.Field
- URL apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+ ID apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Type apijson.Field
+ CallID apijson.Field
+ Cost apijson.Field
+ Filename apijson.Field
+ Files apijson.Field
+ Hash apijson.Field
+ Metadata apijson.Field
+ Mime apijson.Field
+ Name apijson.Field
+ Snapshot apijson.Field
+ Source apijson.Field
+ State apijson.Field
+ Synthetic apijson.Field
+ Text apijson.Field
+ Time apijson.Field
+ Tokens apijson.Field
+ Tool apijson.Field
+ URL apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
}
func (r partJSON) RawJSON() string {
@@ -1175,27 +1187,27 @@ func (r PartType) IsKnown() bool {
}
type ReasoningPart struct {
- ID string `json:"id,required"`
- MessageID string `json:"messageID,required"`
- SessionID string `json:"sessionID,required"`
- Text string `json:"text,required"`
- Type ReasoningPartType `json:"type,required"`
- ProviderMetadata map[string]interface{} `json:"providerMetadata"`
- Time ReasoningPartTime `json:"time"`
- JSON reasoningPartJSON `json:"-"`
+ ID string `json:"id,required"`
+ 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"`
+ Metadata map[string]interface{} `json:"metadata"`
+ JSON reasoningPartJSON `json:"-"`
}
// reasoningPartJSON contains the JSON metadata for the struct [ReasoningPart]
type reasoningPartJSON struct {
- ID apijson.Field
- MessageID apijson.Field
- SessionID apijson.Field
- Text apijson.Field
- Type apijson.Field
- ProviderMetadata apijson.Field
- Time apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+ ID apijson.Field
+ MessageID apijson.Field
+ SessionID apijson.Field
+ Text apijson.Field
+ Time apijson.Field
+ Type apijson.Field
+ Metadata apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
}
func (r *ReasoningPart) UnmarshalJSON(data []byte) (err error) {
@@ -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)
-}
diff --git a/packages/sdk/go/session_test.go b/packages/sdk/go/session_test.go
index b8158f099..61a340e12 100644
--- a/packages/sdk/go/session_test.go
+++ b/packages/sdk/go/session_test.go
@@ -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"
diff --git a/packages/sdk/stainless/stainless.yml b/packages/sdk/stainless/stainless.yml
index 0c85a2cef..eb0f633f5 100644
--- a/packages/sdk/stainless/stainless.yml
+++ b/packages/sdk/stainless/stainless.yml
@@ -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
diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go
index 48b7d67f9..08a79e310 100644
--- a/packages/tui/internal/app/app.go
+++ b/packages/tui/internal/app/app.go
@@ -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,
+ }
+ 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:]...)
+ 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 {
diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go
index 980d5262c..a51f158ce 100644
--- a/packages/tui/internal/components/chat/editor.go
+++ b/packages/tui/internal/components/chat/editor.go
@@ -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
diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go
index 0262f5077..f57470840 100644
--- a/packages/tui/internal/tui/tui.go
+++ b/packages/tui/internal/tui/tui.go
@@ -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)