mirror of
https://github.com/anomalyco/opencode.git
synced 2026-03-12 17:43:56 +00:00
Compare commits
5 Commits
node-pty
...
fix/interr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ed3336b23 | ||
|
|
02a7b0637d | ||
|
|
1b6820bab5 | ||
|
|
89bf199c07 | ||
|
|
5acfdd1c5d |
1
.opencode/.gitignore
vendored
1
.opencode/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
plans/
|
||||
bun.lock
|
||||
package.json
|
||||
package-lock.json
|
||||
|
||||
@@ -9,14 +9,12 @@ test("/terminal toggles the terminal panel", async ({ page, gotoSession }) => {
|
||||
|
||||
await expect(terminal).not.toBeVisible()
|
||||
|
||||
await prompt.click()
|
||||
await page.keyboard.type("/terminal")
|
||||
await prompt.fill("/terminal")
|
||||
await expect(page.locator('[data-slash-id="terminal.toggle"]').first()).toBeVisible()
|
||||
await page.keyboard.press("Enter")
|
||||
await expect(terminal).toBeVisible()
|
||||
|
||||
await prompt.click()
|
||||
await page.keyboard.type("/terminal")
|
||||
await prompt.fill("/terminal")
|
||||
await expect(page.locator('[data-slash-id="terminal.toggle"]').first()).toBeVisible()
|
||||
await page.keyboard.press("Enter")
|
||||
await expect(terminal).not.toBeVisible()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export const promptSelector = '[data-component="prompt-input"]'
|
||||
export const terminalSelector = '[data-component="terminal"]'
|
||||
export const terminalPanelSelector = '#terminal-panel[aria-hidden="false"]'
|
||||
export const terminalSelector = `${terminalPanelSelector} [data-component="terminal"]`
|
||||
export const sessionComposerDockSelector = '[data-component="session-prompt-dock"]'
|
||||
export const questionDockSelector = '[data-component="dock-prompt"][data-kind="question"]'
|
||||
export const permissionDockSelector = '[data-component="dock-prompt"][data-kind="permission"]'
|
||||
|
||||
@@ -132,6 +132,28 @@ export const { use: useNotification, provider: NotificationProvider } = createSi
|
||||
const [index, setIndex] = createStore<NotificationIndex>(buildNotificationIndex(store.list))
|
||||
|
||||
const meta = { pruned: false, disposed: false }
|
||||
const idleSuppressMs = 5000
|
||||
const idleSuppressedUntilBySession = new Map<string, number>()
|
||||
|
||||
const idleSuppressKey = (directory: string, sessionID?: string) => {
|
||||
if (!sessionID) return
|
||||
return `${directory}:${sessionID}`
|
||||
}
|
||||
|
||||
const markIdleSuppressed = (directory: string, sessionID?: string) => {
|
||||
const key = idleSuppressKey(directory, sessionID)
|
||||
if (!key) return
|
||||
idleSuppressedUntilBySession.set(key, Date.now() + idleSuppressMs)
|
||||
}
|
||||
|
||||
const shouldSuppressIdle = (directory: string, sessionID?: string) => {
|
||||
const key = idleSuppressKey(directory, sessionID)
|
||||
if (!key) return false
|
||||
const until = idleSuppressedUntilBySession.get(key)
|
||||
if (until === undefined) return false
|
||||
idleSuppressedUntilBySession.delete(key)
|
||||
return until > Date.now()
|
||||
}
|
||||
|
||||
const updateUnseen = (scope: "session" | "project", key: string, unseen: Notification[]) => {
|
||||
setIndex(scope, "unseen", key, unseen)
|
||||
@@ -290,12 +312,15 @@ export const { use: useNotification, provider: NotificationProvider } = createSi
|
||||
if (event.type !== "session.idle" && event.type !== "session.error") return
|
||||
|
||||
const directory = e.name
|
||||
const time = Date.now()
|
||||
if (event.type === "session.error") {
|
||||
markIdleSuppressed(directory, event.properties.sessionID)
|
||||
}
|
||||
if (event.type === "session.idle") {
|
||||
handleSessionIdle(directory, event, time)
|
||||
if (shouldSuppressIdle(directory, event.properties.sessionID)) return
|
||||
handleSessionIdle(directory, event, Date.now())
|
||||
return
|
||||
}
|
||||
handleSessionError(directory, event, time)
|
||||
handleSessionError(directory, event, Date.now())
|
||||
})
|
||||
onCleanup(() => {
|
||||
meta.disposed = true
|
||||
|
||||
@@ -40,14 +40,6 @@ export namespace ProviderError {
|
||||
return /^4(00|13)\s*(status code)?\s*\(no body\)/i.test(message)
|
||||
}
|
||||
|
||||
function error(providerID: string, error: APICallError) {
|
||||
if (providerID.includes("github-copilot") && error.statusCode === 403) {
|
||||
return "Please reauthenticate with the copilot provider to ensure your credentials work properly with OpenCode."
|
||||
}
|
||||
|
||||
return error.message
|
||||
}
|
||||
|
||||
function message(providerID: string, e: APICallError) {
|
||||
return iife(() => {
|
||||
const msg = e.message
|
||||
@@ -60,10 +52,6 @@ export namespace ProviderError {
|
||||
return "Unknown error"
|
||||
}
|
||||
|
||||
const transformed = error(providerID, e)
|
||||
if (transformed !== msg) {
|
||||
return transformed
|
||||
}
|
||||
if (!e.responseBody || (e.statusCode && msg !== STATUS_CODES[e.statusCode])) {
|
||||
return msg
|
||||
}
|
||||
|
||||
@@ -842,35 +842,6 @@ describe("session.message-v2.fromError", () => {
|
||||
})
|
||||
})
|
||||
|
||||
test("maps github-copilot 403 to reauth guidance", () => {
|
||||
const error = new APICallError({
|
||||
message: "forbidden",
|
||||
url: "https://api.githubcopilot.com/v1/chat/completions",
|
||||
requestBodyValues: {},
|
||||
statusCode: 403,
|
||||
responseHeaders: { "content-type": "application/json" },
|
||||
responseBody: '{"error":"forbidden"}',
|
||||
isRetryable: false,
|
||||
})
|
||||
|
||||
const result = MessageV2.fromError(error, { providerID: "github-copilot" })
|
||||
|
||||
expect(result).toStrictEqual({
|
||||
name: "APIError",
|
||||
data: {
|
||||
message:
|
||||
"Please reauthenticate with the copilot provider to ensure your credentials work properly with OpenCode.",
|
||||
statusCode: 403,
|
||||
isRetryable: false,
|
||||
responseHeaders: { "content-type": "application/json" },
|
||||
responseBody: '{"error":"forbidden"}',
|
||||
metadata: {
|
||||
url: "https://api.githubcopilot.com/v1/chat/completions",
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test("detects context overflow from APICallError provider messages", () => {
|
||||
const cases = [
|
||||
"prompt is too long: 213462 tokens > 200000 maximum",
|
||||
|
||||
Reference in New Issue
Block a user