Compare commits

..

10 Commits

Author SHA1 Message Date
Dax Raad 5a8847952a ci: ignore 2025-07-19 19:29:05 -04:00
Dax Raad 87d21ebf2b Revert "fix: prevent sparse spacing in hyphenated words (#1102)"
This reverts commit 2b44dbdbf1.
2025-07-19 19:25:15 -04:00
Timo Clasen a524fc545c fix(hooks): prevent session_complete hook from firing on subagent sessions (#1149) 2025-07-19 18:20:07 -05:00
Dax Raad 4316edaf43 fix first run github copilot 2025-07-19 19:19:38 -04:00
Dax Raad d845924e8b ci: ignore 2025-07-19 19:00:17 -04:00
Dax Raad a29b322bdd ci: ignore 2025-07-19 18:54:46 -04:00
Dax Raad 9723ffa7a6 ignore: ci 2025-07-19 18:48:43 -04:00
Dax Raad f06cd88773 perf: more performance improvements 2025-07-19 18:41:21 -04:00
Dax Raad 9af92b6914 perf: scroll to bottom in thread 2025-07-19 17:55:01 -04:00
Dax Raad 8f64c4b312 disable todo tools when running as task 2025-07-19 15:54:11 -04:00
12 changed files with 37 additions and 33 deletions
+1
View File
@@ -152,6 +152,7 @@ if (!snapshot) {
for (const pkg of ["opencode", "opencode-bin"]) {
await $`rm -rf ./dist/aur-${pkg}`
await $`git clone ssh://aur@aur.archlinux.org/${pkg}.git ./dist/aur-${pkg}`
await $`cd ./dist/aur-${pkg} && git checkout master`
await Bun.file(`./dist/aur-${pkg}/PKGBUILD`).write(pkgbuild.replace("${pkg}", pkg))
await $`cd ./dist/aur-${pkg} && makepkg --printsrcinfo > .SRCINFO`
await $`cd ./dist/aur-${pkg} && git add PKGBUILD .SRCINFO`
+2 -1
View File
@@ -4,11 +4,12 @@ import path from "path"
export const AuthCopilot = lazy(async () => {
const file = Bun.file(path.join(Global.Path.state, "plugin", "copilot.ts"))
const exists = await file.exists()
const response = fetch("https://raw.githubusercontent.com/sst/opencode-github-copilot/refs/heads/main/auth.ts")
.then((x) => Bun.write(file, x))
.catch(() => {})
if (!file.exists()) {
if (!exists) {
const worked = await response
if (!worked) return
}
+5 -1
View File
@@ -31,9 +31,13 @@ export namespace ConfigHooks {
}
})
Bus.subscribe(Session.Event.Idle, async () => {
Bus.subscribe(Session.Event.Idle, async (payload) => {
const cfg = await Config.get()
if (cfg.experimental?.hook?.session_completed) {
const session = await Session.get(payload.properties.sessionID)
// Only fire hook for top-level sessions (not subagent sessions)
if (session.parentID) return
for (const item of cfg.experimental.hook.session_completed) {
log.info("session_completed", {
command: item.command,
+2
View File
@@ -325,6 +325,7 @@ export namespace Session {
providerID: z.string(),
modelID: z.string(),
mode: z.string().optional(),
tools: z.record(z.boolean()).optional(),
parts: z.array(
z.discriminatedUnion("type", [
MessageV2.TextPart.omit({
@@ -618,6 +619,7 @@ export namespace Session {
for (const item of await Provider.tools(input.providerID)) {
if (mode.tools[item.id] === false) continue
if (input.tools?.[item.id] === false) continue
if (session.parentID && item.id === "task") continue
tools[item.id] = tool({
id: item.id as any,
+4
View File
@@ -41,6 +41,10 @@ export const TaskTool = Tool.define({
sessionID: session.id,
modelID: msg.modelID,
providerID: msg.providerID,
tools: {
todoread: false,
todowrite: false,
},
parts: [
{
id: Identifier.ascending("part"),
+3
View File
@@ -91,6 +91,9 @@ func main() {
stream := httpClient.Event.ListStreaming(ctx)
for stream.Next() {
evt := stream.Current().AsUnion()
if _, ok := evt.(opencode.EventListResponseEventStorageWrite); ok {
continue
}
program.Send(evt)
}
if err := stream.Err(); err != nil {
@@ -196,8 +196,6 @@ func renderText(
case opencode.UserMessage:
ts = time.UnixMilli(int64(casted.Time.Created))
base := styles.NewStyle().Foreground(t.Text()).Background(backgroundColor)
// Process @ mentions and styling with hyphen preservation
words := strings.Fields(text)
for i, word := range words {
if strings.HasPrefix(word, "@") {
@@ -206,14 +204,9 @@ func renderText(
words[i] = base.Render(word + " ")
}
}
styledText := strings.Join(words, "")
// Apply word wrapping with hyphen preservation
frameSize := util.GetMessageContainerFrame()
wrappedText := util.ProcessTextWithHyphens(styledText, func(t string) string {
return ansi.WordwrapWc(t, width-frameSize, " ")
})
content = base.Width(width - frameSize).Render(wrappedText)
text = strings.Join(words, "")
text = ansi.WordwrapWc(text, width-6, " -")
content = base.Width(width - 6).Render(text)
}
timestamp := ts.
@@ -715,4 +708,5 @@ func renderDiagnostics(
// if !ok {
// return ""
// }
}
@@ -53,6 +53,8 @@ func (m *messagesComponent) Init() tea.Cmd {
}
func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
measure := util.Measure("messages.Update")
defer measure("from", fmt.Sprintf("%T", msg))
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.WindowSizeMsg:
@@ -102,9 +104,7 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.loading = false
m.tail = m.viewport.AtBottom()
m.viewport = msg.viewport
if m.tail {
m.viewport.GotoBottom()
}
m.header = msg.header
if m.dirty {
cmds = append(cmds, m.renderView())
}
@@ -120,12 +120,12 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
type renderCompleteMsg struct {
viewport viewport.Model
header string
partCount int
lineCount int
}
func (m *messagesComponent) renderView() tea.Cmd {
m.header = m.renderHeader()
if m.rendering {
slog.Debug("pending render, skipping")
@@ -138,8 +138,10 @@ func (m *messagesComponent) renderView() tea.Cmd {
m.rendering = true
viewport := m.viewport
tail := m.tail
return func() tea.Msg {
header := m.renderHeader()
measure := util.Measure("messages.renderView")
defer measure()
@@ -402,8 +404,12 @@ func (m *messagesComponent) renderView() tea.Cmd {
content := "\n" + strings.Join(blocks, "\n\n")
viewport.SetHeight(m.height - lipgloss.Height(m.header))
viewport.SetContent(content)
if tail {
viewport.GotoBottom()
}
return renderCompleteMsg{
header: header,
viewport: viewport,
partCount: partCount,
lineCount: lineCount,
@@ -2051,10 +2051,6 @@ func wrapInterfaces(content []any, width int) [][]any {
if unicode.IsSpace(r) {
isSpace = true
}
// Use hyphen-aware word boundary detection
if r == '-' {
isSpace = false
}
itemW = rw.RuneWidth(r)
} else if att, ok := item.(*Attachment); ok {
itemW = uniseg.StringWidth(att.Display)
+3 -3
View File
@@ -103,7 +103,7 @@ func (a appModel) Init() tea.Cmd {
}
func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
measure := util.Measure("Update")
measure := util.Measure("app.Update")
defer measure("from", fmt.Sprintf("%T", msg))
var cmd tea.Cmd
@@ -528,17 +528,17 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func (a appModel) View() string {
measure := util.Measure("app.View")
defer measure()
t := theme.CurrentTheme()
var mainLayout string
measure := util.Measure("app.View")
if a.app.Session.ID == "" {
mainLayout = a.home()
} else {
mainLayout = a.chat()
}
measure()
mainLayout = styles.NewStyle().
Background(t.Background()).
Padding(0, 2).
+3 -9
View File
@@ -83,17 +83,11 @@ func Extension(path string) string {
}
func ToMarkdown(content string, width int, backgroundColor compat.AdaptiveColor) string {
renderWidth := width - GetMarkdownContainerFrame()
r := styles.GetMarkdownRenderer(renderWidth, backgroundColor)
r := styles.GetMarkdownRenderer(width-6, backgroundColor)
content = strings.ReplaceAll(content, RootPath+"/", "")
// Apply hyphen preservation during markdown rendering
rendered := ProcessTextWithHyphens(content, func(t string) string {
result, _ := r.Render(t)
return result
})
rendered, _ := r.Render(content)
lines := strings.Split(rendered, "\n")
// Clean up empty lines at start/end
if len(lines) > 0 {
firstLine := lines[0]
cleaned := ansi.Strip(firstLine)
@@ -1,7 +1,6 @@
package viewport
import (
"log/slog"
"math"
"strings"