Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,31 @@ jobs:
git config --global user.email "ci@mimo.ai"
git config --global user.name "mimo-ci"

# runtime-worktree.test.ts excluded from shards: its deadline-fired test
# deadlocks when run after other tests (QuickJS WASM state leak).
# It runs separately below in an isolated process.
- name: Run unit tests (shard ${{ matrix.shard }})
timeout-minutes: 8
working-directory: packages/opencode
run: bun run test:ci --shard ${{ matrix.shard }}
run: |
find test -name '*.test.ts' ! -name 'runtime-worktree.test.ts' | sort > /tmp/test-files.txt
shard=${{ matrix.shard }}
idx=${shard%/*}
n=${shard#*/}
files=$(awk -v i="$idx" -v n="$n" 'NR % n == i - 1' /tmp/test-files.txt)
mkdir -p .artifacts/unit
bun test $files --timeout 120000 --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml

- name: Upload JUnit
if: always()
uses: actions/upload-artifact@v7
with:
name: junit-shard-${{ strategy.job-index }}
path: packages/opencode/.artifacts/unit/junit.xml

# Run deadline worktree test in isolation (shard 4/4 only).
- name: Run deadline worktree test (isolated)
if: matrix.shard == '4/4'
timeout-minutes: 3
working-directory: packages/opencode
run: bun test test/workflow/runtime-worktree.test.ts -t 'deadline-fired' --timeout 120000
23 changes: 17 additions & 6 deletions packages/opencode/src/session/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ interface ProcessorContext extends Input {
stepPartIds: PartID[]
textNgramMonitor: TextNgramMonitor | undefined
textNgramRepeat: boolean
textPartPersisted: boolean
}

type StreamEvent = Event
Expand Down Expand Up @@ -237,6 +238,7 @@ export const layer: Layer.Layer<
stepPartIds: [],
textNgramMonitor: undefined,
textNgramRepeat: false,
textPartPersisted: false,
}
let aborted = false
// Only the main agent owns session-level status. Subagents (explore,
Expand Down Expand Up @@ -652,13 +654,18 @@ export const layer: Layer.Layer<
time: { start: Date.now() },
metadata: value.providerMetadata,
}
yield* session.updatePart(ctx.currentText)
ctx.stepPartIds.push(ctx.currentText.id)
ctx.textPartPersisted = false
return

case "text-delta":
if (!ctx.firstTokenAt) ctx.firstTokenAt = Date.now()
if (!ctx.currentText) return
if (!value.text) return
if (!ctx.textPartPersisted) {
ctx.textPartPersisted = true
yield* session.updatePart(ctx.currentText)
ctx.stepPartIds.push(ctx.currentText.id)
}
ctx.currentText.text += value.text
checkTextNgram(value.text)
if (value.providerMetadata) ctx.currentText.metadata = value.providerMetadata
Expand Down Expand Up @@ -689,7 +696,9 @@ export const layer: Layer.Layer<
ctx.currentText.time = { start: ctx.currentText.time?.start ?? end, end }
}
if (value.providerMetadata) ctx.currentText.metadata = value.providerMetadata
yield* session.updatePart(ctx.currentText)
if (ctx.currentText.text) {
yield* session.updatePart(ctx.currentText)
}
ctx.currentText = undefined
return

Expand Down Expand Up @@ -719,9 +728,11 @@ export const layer: Layer.Layer<
}

if (ctx.currentText) {
const end = Date.now()
ctx.currentText.time = { start: ctx.currentText.time?.start ?? end, end }
yield* session.updatePart(ctx.currentText)
if (ctx.currentText.text) {
const end = Date.now()
ctx.currentText.time = { start: ctx.currentText.time?.start ?? end, end }
yield* session.updatePart(ctx.currentText)
}
ctx.currentText = undefined
}

Expand Down
Loading