summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKit Langton <[email protected]>2026-04-01 22:57:45 -0400
committerGitHub <[email protected]>2026-04-02 02:57:45 +0000
commit916afb5220d064990d846f4080a683762069fa25 (patch)
tree218935c6671e86ae880563e266fcf262e70765b2
parent5daf2fa7f028f21ba79fd36ec2eb8b0603032673 (diff)
downloadopencode-916afb5220d064990d846f4080a683762069fa25.tar.gz
opencode-916afb5220d064990d846f4080a683762069fa25.zip
refactor(account): share token freshness helper (#20591)
-rw-r--r--packages/opencode/src/account/index.ts8
-rw-r--r--packages/opencode/test/account/service.test.ts11
2 files changed, 13 insertions, 6 deletions
diff --git a/packages/opencode/src/account/index.ts b/packages/opencode/src/account/index.ts
index 947fadad0..bcc90b7b1 100644
--- a/packages/opencode/src/account/index.ts
+++ b/packages/opencode/src/account/index.ts
@@ -120,6 +120,10 @@ class TokenRefreshRequest extends Schema.Class<TokenRefreshRequest>("TokenRefres
const clientId = "opencode-cli"
const eagerRefreshThreshold = Duration.minutes(5)
+const eagerRefreshThresholdMs = Duration.toMillis(eagerRefreshThreshold)
+
+const isTokenFresh = (tokenExpiry: number | null, now: number) =>
+ tokenExpiry != null && tokenExpiry > now + eagerRefreshThresholdMs
const mapAccountServiceError =
(message = "Account service operation failed") =>
@@ -219,7 +223,7 @@ export namespace Account {
const account = maybeAccount.value
const now = yield* Clock.currentTimeMillis
- if (account.token_expiry && account.token_expiry > now + Duration.toMillis(eagerRefreshThreshold)) {
+ if (isTokenFresh(account.token_expiry, now)) {
return account.access_token
}
@@ -229,7 +233,7 @@ export namespace Account {
const resolveToken = Effect.fnUntraced(function* (row: AccountRow) {
const now = yield* Clock.currentTimeMillis
- if (row.token_expiry && row.token_expiry > now + Duration.toMillis(eagerRefreshThreshold)) {
+ if (isTokenFresh(row.token_expiry, now)) {
return row.access_token
}
diff --git a/packages/opencode/test/account/service.test.ts b/packages/opencode/test/account/service.test.ts
index e4c43a1f6..85ab259f1 100644
--- a/packages/opencode/test/account/service.test.ts
+++ b/packages/opencode/test/account/service.test.ts
@@ -18,6 +18,9 @@ const truncate = Layer.effectDiscard(
const it = testEffect(Layer.merge(AccountRepo.layer, truncate))
+const insideEagerRefreshWindow = Duration.toMillis(Duration.minutes(1))
+const outsideEagerRefreshWindow = Duration.toMillis(Duration.minutes(10))
+
const live = (client: HttpClient.HttpClient) =>
Account.layer.pipe(Layer.provide(Layer.succeed(HttpClient.HttpClient, client)))
@@ -63,7 +66,7 @@ it.live("orgsByAccount groups orgs per account", () =>
url: "https://one.example.com",
accessToken: AccessToken.make("at_1"),
refreshToken: RefreshToken.make("rt_1"),
- expiry: Date.now() + 10 * 60_000,
+ expiry: Date.now() + outsideEagerRefreshWindow,
orgID: Option.none(),
}),
)
@@ -75,7 +78,7 @@ it.live("orgsByAccount groups orgs per account", () =>
url: "https://two.example.com",
accessToken: AccessToken.make("at_2"),
refreshToken: RefreshToken.make("rt_2"),
- expiry: Date.now() + 10 * 60_000,
+ expiry: Date.now() + outsideEagerRefreshWindow,
orgID: Option.none(),
}),
)
@@ -159,7 +162,7 @@ it.live("token refreshes before expiry when inside the eager refresh window", ()
url: "https://one.example.com",
accessToken: AccessToken.make("at_old"),
refreshToken: RefreshToken.make("rt_old"),
- expiry: Date.now() + 60_000,
+ expiry: Date.now() + insideEagerRefreshWindow,
orgID: Option.none(),
}),
)
@@ -267,7 +270,7 @@ it.live("config sends the selected org header", () =>
url: "https://one.example.com",
accessToken: AccessToken.make("at_1"),
refreshToken: RefreshToken.make("rt_1"),
- expiry: Date.now() + 10 * 60_000,
+ expiry: Date.now() + outsideEagerRefreshWindow,
orgID: Option.none(),
}),
)