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
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@

This file tracks product releases for Roomote (single monorepo version). Automated release entries are prepended by `pnpm run version`.

## 0.34.0 (2026-08-04)

This release adds Granola and Requesty connections, introduces Mind reader mode for expanded model thoughts, and improves task reliability across mixed-provider workspaces and chat delivery failures.

### Highlights

- Connect Granola once for deployment-wide access to approved meeting notes, folders, and transcripts.
- Connect Requesty from setup or model settings with a curated catalog of current supported models.
- Expand model thought blocks by default with the optional Mind reader mode.
- Launch tasks reliably from workspaces that combine repositories across supported source-control providers.

### Minor changes

- Let deployment administrators connect Granola once so Roomote can securely browse the notes, folders, and transcripts allowed by the configured API key.
- Add an optional Mind reader mode that expands LLM thought blocks by default while preserving manual conversation-level choices.
- Let users connect Requesty from setup or model settings and start with a curated catalog of current supported models.

### Patch changes

- Use Roomote's stable branded Discord invite from the repository and in-app release notes.
- Keep tasks running when agents attempt to read unsupported ICO or CUR files by returning a recoverable tool error before provider submission.
- Launch tasks reliably from workspaces that combine repositories across GitHub, GitLab, Gitea, Azure DevOps, and Bitbucket with provider-scoped credentials. Thanks to @jantekb for reporting [#1082](https://github.com/RooCodeInc/Roomote/issues/1082).
- Require an active deployment administrator to create or update shared environments through Roomote's MCP tools.
- Stop completed chat tasks from entering repeated closeout attempts when message delivery has failed permanently.

## 0.33.0 (2026-08-04)

This release adds new ways to connect and invoke Roomote, gives deployments clearer account-linking guidance, and improves automation and Amazon Bedrock model discovery.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ code. "Fix the typo on the pricing page" works.

## Community

- [Discord](https://discord.gg/KNw7Sz75UK): questions, showcase, feature requests
- [Discord](https://discord.gg/roomote): questions, showcase, feature requests
- [GitHub Issues](https://github.com/RooCodeInc/Roomote/issues): bug reports
and feature requests

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 39 additions & 7 deletions apps/api/src/handlers/environments/createEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ import {
inArray,
repositories,
taskRuns,
users,
} from '@roomote/db/server';
import {
type TaskPayload,
environmentConfigSchema,
getAmbiguousEnvironmentRepositoryError,
getDuplicateEnvironmentRepositoryConfigError,
getMissingEnvironmentRepositoryError,
getEnvironmentRepositoryInstallationError,
} from '@roomote/types';
Expand All @@ -30,6 +33,8 @@ export const DUPLICATE_ENVIRONMENT_NAME_ERROR =
'An environment with this name already exists. This endpoint only creates new environments.';
export const EVAL_ENVIRONMENT_WRITE_ERROR =
'isEval is reserved for internal eval environments.';
export const ENVIRONMENT_ADMIN_REQUIRED_ERROR =
'Admin access is required to create or update environments.';

type PostgresErrorLike = {
code?: string;
Expand Down Expand Up @@ -69,7 +74,10 @@ export function getEnvironmentRepositoryConfigError(
installationId: string | number | null | undefined;
}>,
): string | null {
return getEnvironmentRepositoryInstallationError(repositoryRows);
return (
getAmbiguousEnvironmentRepositoryError(repositoryRows) ??
getEnvironmentRepositoryInstallationError(repositoryRows)
);
}

function extractRunId(auth: McpAuth): number | null {
Expand Down Expand Up @@ -109,18 +117,29 @@ export async function resolveEnvironmentWriteUserId(
runId: extractRunId(auth) ?? undefined,
});
} catch (error) {
// A malformed run token or a missing task run means there is no
// resolvable live actor; fall back to mint-time attribution. Unexpected
// lookup failures degrade the same way (matching pre-live-actor
// behavior) instead of escaping the handler's structured error path.
// Environment writes must fail closed when a run token is malformed, its
// task run no longer exists, or the live-actor lookup otherwise fails.
if (!(error instanceof McpProxyError)) {
logHandlerError('resolveEnvironmentWriteUserId', error);
}

return null;
}

return liveActingUserId ?? auth.userId ?? null;
}

export async function canAdministerEnvironments(
userId: string,
): Promise<boolean> {
const user = await db.query.users.findFirst({
where: eq(users.id, userId),
columns: { role: true, deletedAt: true },
});

return user?.role === 'admin' && user.deletedAt == null;
}

/**
* When environment creation/update is triggered by a running task run, persist
* the resulting environment id on that job payload so the UI can resolve
Expand Down Expand Up @@ -211,8 +230,8 @@ export async function createEnvironment(
const auth = c.get('mcpAuth');
const userId = await resolveEnvironmentWriteUserId(auth);

if (!userId) {
return c.json({ error: 'User context required' }, 403);
if (!userId || !(await canAdministerEnvironments(userId))) {
return c.json({ error: ENVIRONMENT_ADMIN_REQUIRED_ERROR }, 403);
}

let body: unknown;
Expand Down Expand Up @@ -252,6 +271,19 @@ export async function createEnvironment(
}

const config = parsedConfig.data;
const duplicateRepositoryError = getDuplicateEnvironmentRepositoryConfigError(
config.repositories,
);

if (duplicateRepositoryError) {
return c.json(
{
error: `Invalid environment configuration: ${duplicateRepositoryError}`,
},
400,
);
}

try {
const existing = await db.query.environments.findFirst({
where: eq(environments.name, config.name),
Expand Down
Loading
Loading