diff --git a/packages/opencode/migration/20260228200329_account-workspace-id/migration.sql b/packages/opencode/migration/20260228200329_account-workspace-id/migration.sql new file mode 100644 index 0000000000..7572fed8b8 --- /dev/null +++ b/packages/opencode/migration/20260228200329_account-workspace-id/migration.sql @@ -0,0 +1,2 @@ +ALTER TABLE `account` ADD `workspace_id` text;--> statement-breakpoint +ALTER TABLE `account` DROP COLUMN `active`; \ No newline at end of file diff --git a/packages/opencode/migration/20260228200329_account-workspace-id/snapshot.json b/packages/opencode/migration/20260228200329_account-workspace-id/snapshot.json new file mode 100644 index 0000000000..e46b5fe1fa --- /dev/null +++ b/packages/opencode/migration/20260228200329_account-workspace-id/snapshot.json @@ -0,0 +1,1018 @@ +{ + "version": "7", + "dialect": "sqlite", + "id": "1f59b6d9-6292-4cbd-8db1-7e5631d46b77", + "prevIds": [ + "b8dc7400-9dbb-4556-b353-68e6b3d4906e" + ], + "ddl": [ + { + "name": "account", + "entityType": "tables" + }, + { + "name": "workspace", + "entityType": "tables" + }, + { + "name": "project", + "entityType": "tables" + }, + { + "name": "message", + "entityType": "tables" + }, + { + "name": "part", + "entityType": "tables" + }, + { + "name": "permission", + "entityType": "tables" + }, + { + "name": "session", + "entityType": "tables" + }, + { + "name": "todo", + "entityType": "tables" + }, + { + "name": "session_share", + "entityType": "tables" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "email", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "url", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "access_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "refresh_token", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "token_expiry", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "workspace_id", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "account" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "account" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "workspace" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "branch", + "entityType": "columns", + "table": "workspace" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "project_id", + "entityType": "columns", + "table": "workspace" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "config", + "entityType": "columns", + "table": "workspace" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "worktree", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "vcs", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "name", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "icon_url", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "icon_color", + "entityType": "columns", + "table": "project" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "project" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "project" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_initialized", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "sandboxes", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "commands", + "entityType": "columns", + "table": "project" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "message" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "session_id", + "entityType": "columns", + "table": "message" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "message" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "message" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "data", + "entityType": "columns", + "table": "message" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "part" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "message_id", + "entityType": "columns", + "table": "part" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "session_id", + "entityType": "columns", + "table": "part" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "part" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "part" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "data", + "entityType": "columns", + "table": "part" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "project_id", + "entityType": "columns", + "table": "permission" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "permission" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "permission" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "data", + "entityType": "columns", + "table": "permission" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "project_id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "parent_id", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "slug", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "directory", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "title", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "version", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "share_url", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "summary_additions", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "summary_deletions", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "summary_files", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "summary_diffs", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "revert", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "permission", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_compacting", + "entityType": "columns", + "table": "session" + }, + { + "type": "integer", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_archived", + "entityType": "columns", + "table": "session" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "session_id", + "entityType": "columns", + "table": "todo" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "content", + "entityType": "columns", + "table": "todo" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "status", + "entityType": "columns", + "table": "todo" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "priority", + "entityType": "columns", + "table": "todo" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "position", + "entityType": "columns", + "table": "todo" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "todo" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "todo" + }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "session_id", + "entityType": "columns", + "table": "session_share" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "id", + "entityType": "columns", + "table": "session_share" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "secret", + "entityType": "columns", + "table": "session_share" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "url", + "entityType": "columns", + "table": "session_share" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "session_share" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "session_share" + }, + { + "columns": [ + "project_id" + ], + "tableTo": "project", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_workspace_project_id_project_id_fk", + "entityType": "fks", + "table": "workspace" + }, + { + "columns": [ + "session_id" + ], + "tableTo": "session", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_message_session_id_session_id_fk", + "entityType": "fks", + "table": "message" + }, + { + "columns": [ + "message_id" + ], + "tableTo": "message", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_part_message_id_message_id_fk", + "entityType": "fks", + "table": "part" + }, + { + "columns": [ + "project_id" + ], + "tableTo": "project", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_permission_project_id_project_id_fk", + "entityType": "fks", + "table": "permission" + }, + { + "columns": [ + "project_id" + ], + "tableTo": "project", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_session_project_id_project_id_fk", + "entityType": "fks", + "table": "session" + }, + { + "columns": [ + "session_id" + ], + "tableTo": "session", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_todo_session_id_session_id_fk", + "entityType": "fks", + "table": "todo" + }, + { + "columns": [ + "session_id" + ], + "tableTo": "session", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_session_share_session_id_session_id_fk", + "entityType": "fks", + "table": "session_share" + }, + { + "columns": [ + "session_id", + "position" + ], + "nameExplicit": false, + "name": "todo_pk", + "entityType": "pks", + "table": "todo" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "account_pk", + "table": "account", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "workspace_pk", + "table": "workspace", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "project_pk", + "table": "project", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "message_pk", + "table": "message", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "part_pk", + "table": "part", + "entityType": "pks" + }, + { + "columns": [ + "project_id" + ], + "nameExplicit": false, + "name": "permission_pk", + "table": "permission", + "entityType": "pks" + }, + { + "columns": [ + "id" + ], + "nameExplicit": false, + "name": "session_pk", + "table": "session", + "entityType": "pks" + }, + { + "columns": [ + "session_id" + ], + "nameExplicit": false, + "name": "session_share_pk", + "table": "session_share", + "entityType": "pks" + }, + { + "columns": [ + { + "value": "session_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "message_session_idx", + "entityType": "indexes", + "table": "message" + }, + { + "columns": [ + { + "value": "message_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "part_message_idx", + "entityType": "indexes", + "table": "part" + }, + { + "columns": [ + { + "value": "session_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "part_session_idx", + "entityType": "indexes", + "table": "part" + }, + { + "columns": [ + { + "value": "project_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "session_project_idx", + "entityType": "indexes", + "table": "session" + }, + { + "columns": [ + { + "value": "parent_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "session_parent_idx", + "entityType": "indexes", + "table": "session" + }, + { + "columns": [ + { + "value": "session_id", + "isExpression": false + } + ], + "isUnique": false, + "where": null, + "origin": "manual", + "name": "todo_session_idx", + "entityType": "indexes", + "table": "todo" + } + ], + "renames": [] +} \ No newline at end of file diff --git a/packages/opencode/src/account/account.sql.ts b/packages/opencode/src/account/account.sql.ts index 3073ca02f1..67dfccf6ab 100644 --- a/packages/opencode/src/account/account.sql.ts +++ b/packages/opencode/src/account/account.sql.ts @@ -8,8 +8,6 @@ export const AccountTable = sqliteTable("account", { access_token: text().notNull(), refresh_token: text().notNull(), token_expiry: integer(), - active: integer({ mode: "boolean" }) - .notNull() - .$default(() => false), + workspace_id: text(), ...Timestamps, }) diff --git a/packages/opencode/src/account/index.ts b/packages/opencode/src/account/index.ts index 47ef6ebbfd..d6b503cf33 100644 --- a/packages/opencode/src/account/index.ts +++ b/packages/opencode/src/account/index.ts @@ -1,4 +1,4 @@ -import { eq } from "drizzle-orm" +import { eq, sql, isNotNull } from "drizzle-orm" import { Database } from "@/storage/db" import { AccountTable } from "./account.sql" import z from "zod" @@ -8,6 +8,7 @@ export namespace Account { id: z.string(), email: z.string(), url: z.string(), + workspace_id: z.string().nullable(), }) export type Account = z.infer @@ -16,11 +17,12 @@ export namespace Account { id: row.id, email: row.email, url: row.url, + workspace_id: row.workspace_id, } } export function active(): Account | undefined { - const row = Database.use((db) => db.select().from(AccountTable).where(eq(AccountTable.active, true)).get()) + const row = Database.use((db) => db.select().from(AccountTable).where(isNotNull(AccountTable.workspace_id)).get()) return row ? fromRow(row) : undefined } @@ -28,6 +30,16 @@ export namespace Account { return Database.use((db) => db.select().from(AccountTable).all().map(fromRow)) } + export function remove(accountID: string) { + Database.use((db) => db.delete(AccountTable).where(eq(AccountTable.id, accountID)).run()) + } + + export function use(accountID: string, workspaceID: string | null) { + Database.use((db) => + db.update(AccountTable).set({ workspace_id: workspaceID }).where(eq(AccountTable.id, accountID)).run(), + ) + } + export async function workspaces(accountID: string): Promise<{ id: string; name: string }[]> { const row = Database.use((db) => db.select().from(AccountTable).where(eq(AccountTable.id, accountID)).get()) if (!row) return [] @@ -45,6 +57,22 @@ export namespace Account { return json.map((x) => ({ id: x.id ?? "", name: x.name ?? "" })) } + export async function config(accountID: string, workspaceID: string): Promise | undefined> { + const row = Database.use((db) => db.select().from(AccountTable).where(eq(AccountTable.id, accountID)).get()) + if (!row) return undefined + + const access = await token(accountID) + if (!access) return undefined + + const res = await fetch(`${row.url}/api/config`, { + headers: { authorization: `Bearer ${access}`, "x-org-id": workspaceID }, + }) + + if (!res.ok) return undefined + const result = (await res.json()) as Record + return result.config + } + export async function token(accountID: string): Promise { const row = Database.use((db) => db.select().from(AccountTable).where(eq(AccountTable.id, accountID)).get()) if (!row) return undefined @@ -164,17 +192,24 @@ export namespace Account { const expiry = Date.now() + json.expires_in! * 1000 const refresh = json.refresh_token ?? "" + // Fetch workspaces and get first one + const orgsRes = await fetch(`${input.server}/api/orgs`, { + headers: { authorization: `Bearer ${access}` }, + }) + const orgs = (await orgsRes.json()) as Array<{ id?: string; name?: string }> + const firstWorkspaceId = orgs.length > 0 ? orgs[0].id : null + Database.use((db) => { - db.update(AccountTable).set({ active: false }).run() + db.update(AccountTable).set({ workspace_id: null }).run() db.insert(AccountTable) .values({ id, email, - url: input.url, + url: input.server, access_token: access, refresh_token: refresh, token_expiry: expiry, - active: true, + workspace_id: firstWorkspaceId, }) .onConflictDoUpdate({ target: AccountTable.id, @@ -182,7 +217,7 @@ export namespace Account { access_token: access, refresh_token: refresh, token_expiry: expiry, - active: true, + workspace_id: firstWorkspaceId, }, }) .run() diff --git a/packages/opencode/src/cli/cmd/account.ts b/packages/opencode/src/cli/cmd/account.ts index 00fbcf2085..ef1c64c806 100644 --- a/packages/opencode/src/cli/cmd/account.ts +++ b/packages/opencode/src/cli/cmd/account.ts @@ -70,20 +70,92 @@ export const LoginCommand = cmd({ }) export const LogoutCommand = cmd({ - command: "logout", + command: "logout [email]", describe: "log out from an account", - async handler() {}, + builder: (yargs) => + yargs.positional("email", { + describe: "account email to log out from", + type: "string", + }), + async handler(args) { + const email = args.email as string | undefined + + if (email) { + const accounts = Account.list() + const match = accounts.find((a) => a.email === email) + if (!match) { + UI.println("Account not found: " + email) + return + } + Account.remove(match.id) + UI.println("Logged out from " + email) + return + } + + const active = Account.active() + if (!active) { + UI.println("Not logged in") + return + } + Account.remove(active.id) + UI.println("Logged out from " + active.email) + }, }) export const SwitchCommand = cmd({ command: "switch", describe: "switch active workspace", - async handler() {}, + async handler() { + UI.empty() + + const active = Account.active() + if (!active) { + UI.println("Not logged in") + return + } + + const workspaces = await Account.workspaces(active.id) + if (workspaces.length === 0) { + UI.println("No workspaces found") + return + } + + prompts.intro("Switch workspace") + + const opts = workspaces.map((w) => ({ + value: w.id, + label: w.id === active.workspace_id ? w.name + UI.Style.TEXT_DIM + " (active)" : w.name, + })) + + const selected = await prompts.select({ + message: "Select workspace", + options: opts, + }) + + if (prompts.isCancel(selected)) return + + Account.use(active.id, selected as string) + prompts.outro("Switched to " + workspaces.find((w) => w.id === selected)?.name) + }, }) export const WorkspacesCommand = cmd({ command: "workspaces", aliases: ["workspace"], describe: "list all workspaces", - async handler() {}, + async handler() { + const accounts = Account.list() + + if (accounts.length === 0) { + UI.println("No accounts found") + return + } + + for (const account of accounts) { + const workspaces = await Account.workspaces(account.id) + for (const space of workspaces) { + UI.println([space.name, account.email, space.id].join("\t")) + } + } + }, }) diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 5e458b7bd0..405bd8b979 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -107,11 +107,6 @@ export namespace Config { } } - const active = Account.active() - const token = active ? await Account.token(active.id) : undefined - if (token) { - } - // Global user config overrides remote config. result = mergeConfigConcatArrays(result, await global()) @@ -178,6 +173,15 @@ export namespace Config { log.debug("loaded custom config from OPENCODE_CONFIG_CONTENT") } + const active = Account.active() + if (active?.workspace_id) { + const config = await Account.config(active.id, active.workspace_id) + result = mergeConfigConcatArrays(result, config ?? {}) + const token = await Account.token(active.id) + // TODO: this is bad + process.env["OPENCODE_CONTROL_TOKEN"] = token + } + // Load managed config files last (highest priority) - enterprise admin-controlled // Kept separate from directories array to avoid write operations when installing plugins // which would fail on system directories requiring elevated permissions