Skip to content

LAU-31: Begining of smth cool#28

Merged
dkarasiewicz merged 8 commits intomainfrom
feature/lau-31-refine-ui
Feb 2, 2026
Merged

LAU-31: Begining of smth cool#28
dkarasiewicz merged 8 commits intomainfrom
feature/lau-31-refine-ui

Conversation

@dkarasiewicz
Copy link
Owner

Summary

Short description of the change.

Related issue(s)

Fixes:

Type of change

  • Bugfix
  • New feature
  • Documentation
  • Refactor
  • Tests
  • Other (please describe):

Component

  • Core application (BSL 1.1)
  • SDK / client library (MIT)
  • Documentation

Description

A more detailed description of changes and rationale.

How to test

n/a

Checklist

  • I added tests that cover my changes (if applicable)
  • I ran linting and type checks locally
  • I updated relevant documentation / README
  • I added or updated changelog/release notes (if required)
  • I followed the collaboration guidelines: ./CONTRIBUTING.md
  • I understand my contribution is licensed under BSL 1.1 (core) or MIT (SDKs)

Screenshots (if UI)

n/a

Release notes

First version of Linea - product copilot

- Replace `LINEA_AGENT` with `AgentFactory` for agent retrieval
- Remove unused imports and adjust card components layout
Copilot AI review requested due to automatic review settings February 2, 2026 13:15
@linear
Copy link

linear bot commented Feb 2, 2026

LAU-31 Refine UI

@vercel
Copy link

vercel bot commented Feb 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v0-landing-page-copy Ready Ready Preview, Comment, Open in v0 Feb 2, 2026 2:07pm

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the initial “Linea” product copilot foundations: a new integrations domain (OAuth + webhooks), expanded Linea services (skills, onboarding, jobs, admin APIs), and supporting UI/docs updates.

Changes:

  • Added core-integration domain with token encryption, OAuth/webhook ingestion, and provider clients (Linear/Slack/GitHub/Google).
  • Expanded Linea with workspace-specific prompts, skills injection, inbox thread creation/events, jobs scheduling, and admin GraphQL endpoints.
  • Updated customer UI auth flow/pages and added extensive docs for integrations, architecture, and demos.

Reviewed changes

Copilot reviewed 91 out of 159 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
libs/core/linea/src/lib/services/index.ts Re-exports new Linea services/factories for broader module usage.
libs/core/linea/src/lib/services/identity-linking-graphs.service.ts Adds identity linking graph to connect GitHub/Linear/Slack accounts into memories.
libs/core/linea/src/lib/services/heartbeat-settings.service.ts Adds heartbeat settings persistence via MemoryService.
libs/core/linea/src/lib/services/graphs.factory.ts Enriches GitHub signal normalization and adds PR context extraction.
libs/core/linea/src/lib/services/agent.factory.ts Adds workspace-specific agents, skills injection, and prompt composition.
libs/core/linea/src/lib/services/agent-prompt.service.ts Introduces workspace prompt persistence via MemoryService.
libs/core/linea/src/lib/providers/models.provider.ts Changes model configuration by removing explicit temperature setting.
libs/core/linea/src/lib/prompts/subagents.ts Adds prompts for specialized subagents.
libs/core/linea/src/lib/prompts/index.ts Refactors prompt exports into separate prompt modules.
libs/core/linea/src/lib/prompts/agent.ts Defines new system prompt and helper to build workspace-aware prompts.
libs/core/linea/src/lib/linea.module.ts Wires IntegrationModule, Bull queue, admin resolver, jobs, and new services.
libs/core/linea/src/lib/linea.facade.ts Updates facade to use AgentFactory and adds inbox thread creation / graph config.
libs/core/linea/src/lib/linea.events.ts Introduces Linea pub-sub event constants.
libs/core/linea/src/lib/linea-admin.resolver.ts Adds GraphQL admin endpoints for jobs, memories, prompts, skills, settings, team graph.
libs/core/linea/src/lib/linea-admin.models.ts Adds GraphQL types/inputs for Linea admin features.
libs/core/linea/src/lib/jobs/linea-jobs.types.ts Defines job payload formats for heartbeat + scheduled tasks.
libs/core/linea/src/lib/jobs/linea-jobs.service.ts Implements BullMQ job scheduling and listing.
libs/core/linea/src/lib/jobs/linea-jobs.constants.ts Adds queue/job constants and heartbeat interval.
libs/core/linea/src/lib/assistant.service.ts Enhances thread listing, adds inbox thread creation + pubsub emission, inbox status updates.
libs/core/linea/src/lib/assistant.controller.ts Switches to workspace-aware DeepAgent usage and adds workspace prompt endpoints.
libs/core/linea/src/index.ts Exposes additional Linea services and types to other packages/apps.
libs/core/integration/tsconfig.spec.json Adds Jest/Node TS config for integration library tests.
libs/core/integration/tsconfig.lib.json Adds library TS build config for integration package.
libs/core/integration/tsconfig.json Adds base TS project references for integration package.
libs/core/integration/src/lib/slack.service.ts Adds Slack Web API wrapper (channels/users/messages/post).
libs/core/integration/src/lib/slack-bolt.service.ts Adds Slack Bolt receiver mounting and event forwarding into webhook service.
libs/core/integration/src/lib/linear.service.ts Adds Linear SDK wrapper + webhook signature verification + token refresh.
libs/core/integration/src/lib/integration.webhook.service.ts Adds webhook processing for Linear/Slack/GitHub and publishes events to event bus.
libs/core/integration/src/lib/integration.service.ts Adds Integration CRUD, AES-GCM token encryption/decryption, refresh-on-expiry.
libs/core/integration/src/lib/integration.resolver.ts Adds GraphQL queries/mutations for integration listing and deletion.
libs/core/integration/src/lib/integration.module.ts Declares integration domain providers/controllers/resolver/facade.
libs/core/integration/src/lib/integration.models.ts Adds GraphQL models/enums and OAuth input/state types.
libs/core/integration/src/lib/integration.facade.ts Adds cross-domain integration accessor (tokens + active integrations).
libs/core/integration/src/lib/google.service.ts Adds Google OAuth token refresh + Gmail/Calendar API helpers.
libs/core/integration/src/index.ts Exports integration module/services/models.
libs/core/integration/project.json Registers Nx project for the integration domain library.
libs/core/integration/jest.config.cts Adds Jest config for the integration library.
libs/core/integration/eslint.config.mjs Adds ESLint config passthrough for integration library.
libs/core/integration/README.md Adds minimal integration library README.
libs/core/common/src/lib/models/domain.model.ts Adds Integration domain + events and payload models for the event bus.
libs/core/common/src/lib/models/auth.model.ts Adds primaryWorkspaceId and AuthenticatedWorkspace type.
libs/core/common/src/lib/jobs/jobs.module.ts Adds global BullMQ root configuration for Redis connection.
libs/core/common/src/lib/interfaces/auth.interface.ts Adds primaryWorkspaceId to UserDTO interface.
libs/core/common/src/lib/decorators/index.ts Exports new CurrentWorkspace decorator.
libs/core/common/src/lib/decorators/current-workspace.decorator.ts Implements CurrentWorkspace decorator (HTTP + GraphQL).
libs/core/common/src/lib/db/schema.ts Adds Integration table/enums and adds primaryWorkspaceId to User schema.
libs/core/common/src/lib/common.module.ts Registers JobsModule in CommonModule.
libs/core/auth/src/lib/auth.service.ts Persists/returns primaryWorkspaceId for users.
libs/core/auth/src/lib/auth.queue.ts Passes workspaceId into user creation as primaryWorkspaceId.
docs/guides/slack-setup.md Adds Slack integration setup documentation.
docs/guides/linear-setup.md Adds Linear integration setup documentation.
docs/guides/demo.md Adds a short demo script for showcasing product value.
docs/guides/configuration.md Adds consolidated configuration/environment variable guide.
docs/architecture/tool-uis.md Documents UI components that render tool outputs.
docs/architecture/skills.md Documents skills structure and how skills are loaded/exposed to agents.
docs/architecture/overview.md Adds high-level system architecture overview.
docs/architecture/linea.md Documents Linea’s architecture/capabilities/data flow.
docs/architecture/integrations.md Documents integrations domain responsibilities and flows.
docs/README.md Adds docs entrypoint/index.
apps/customer-ui/src/lib/server-auth.ts Adds server-side current-user lookup helper for route guards.
apps/customer-ui/src/app/onboarding/page.tsx Defaults integrations onboarding feature flag to enabled.
apps/customer-ui/src/app/login/page.tsx Converts login page into server component that redirects if already authenticated.
apps/customer-ui/src/app/login/login-client.tsx Moves interactive login steps into a client component.
apps/customer-ui/src/app/login/loading.tsx Adds loading UI for login route.
apps/customer-ui/src/app/layout.tsx Normalizes NEXT_PUBLIC_API_URL and tweaks metadata punctuation.
apps/customer-ui/src/app/inbox/team/page.tsx Adds server-side auth guard for team page.
apps/customer-ui/src/app/inbox/settings/page.tsx Replaces large client settings page with server-guarded SettingsClient entrypoint.
apps/customer-ui/src/app/inbox/layout.tsx Removes InboxProvider wrapper (layout deleted).
apps/customer-ui/next.config.js Adds proxy rewrite for /integrations/* routes.
apps/core/src/demo-seed.ts Adds demo seeding script for inbox items, prompt, skills, and heartbeat scheduling.
apps/core/src/app/configuration.ts Adds integrations/app URLs to config schema and env mapping.
apps/core/src/app/app.module.ts Registers IntegrationModule and pipes currentWorkspaceId into GraphQL context.
apps/core/project.json Adds Nx target to run demo seed script.
apps/core/migrations/meta/_journal.json Records new migration entries for integration/user changes.
apps/core/migrations/0002_small_squadron_sinister.sql Updates Integration schema (drop webhook fields, add google enum value).
apps/core/migrations/0001_oval_sentinel.sql Adds Integration table/enums and primaryWorkspaceId to User.
README.md Rewrites root README to a shorter product/demo/dev overview.
.env.example Adds integration/env URL variables and provider secrets placeholders.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +251 to +258
if (!payload?.prompt || typeof payload.prompt !== 'string') {
throw new BadRequestException('Prompt is required');
}

const trimmedPrompt = payload.prompt.trim();
if (!trimmedPrompt) {
throw new BadRequestException('Prompt cannot be empty');
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BadRequestException is used but not imported in this file. Add it to the @nestjs/common import list so this compiles.

Copilot uses AI. Check for mistakes.
Comment on lines 269 to 274
@Get('/thread/:threadId/state')
async getThreadState(
@CurrentUser() currentUser: AuthenticatedUser,
@CurrentWorkspace() workspace: AuthenticatedWorkspace,
@Query('threadId') threadId: string,
): Promise<StateSnapshot> {
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

threadId is part of the route path (/thread/:threadId/state) but is read from the query string. Replace @Query('threadId') with @Param('threadId') (and import Param) so callers hitting /thread/abc/state work correctly.

Copilot uses AI. Check for mistakes.
Comment on lines 294 to 299
async getThreadState(threadId: string) {
return this.agent.getState({
const agent = await this.agentFactory.getAgentForWorkspace('default');
return agent.getState({
configurable: { thread_id: threadId },
});
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hard-codes the workspace id to 'default', which will return the wrong agent/state for non-default workspaces. Pass the real workspace id into getThreadState (or derive it from context) and use that when calling getAgentForWorkspace.

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +58
const isValid = this.linearService.verifyWebhookSignature(
rawBody,
signature,
this.configService.get('integrations.linear.webhookSecret') as string,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The config schema marks integrations.linear.webhookSecret as optional, but this code always passes it into signature verification. If it’s undefined, createHmac will throw and webhook processing will 500. Either (1) make the secret required in config, or (2) explicitly handle the missing-secret case (e.g., skip verification with a clear warning, or reject the webhook with processed: false).

Suggested change
const isValid = this.linearService.verifyWebhookSignature(
rawBody,
signature,
this.configService.get('integrations.linear.webhookSecret') as string,
const webhookSecret = this.configService.get<string>(
'integrations.linear.webhookSecret',
);
if (!webhookSecret) {
this.logger.error(
{ organizationId, integrationId: integrationRecord.id },
'Linear webhook secret not configured; rejecting webhook',
);
return { processed: false };
}
const isValid = this.linearService.verifyWebhookSignature(
rawBody,
signature,
webhookSecret,

Copilot uses AI. Check for mistakes.
Comment on lines +165 to +174
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');

// Linear sends the signature as a hex string
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature),
);
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As written, timingSafeEqual can throw if the incoming signature length differs, which can turn malformed/hostile requests into 500s. Also, Buffer.from(signature) uses UTF-8 bytes, not hex decoding, so you’re comparing ASCII bytes rather than raw digest bytes. Prefer decoding both with Buffer.from(..., 'hex') and guard on equal length (or wrap in try/catch and return false on any error).

Suggested change
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
// Linear sends the signature as a hex string
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature),
);
try {
const expectedSignatureHex = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
// Linear sends the signature as a hex string; decode both values from hex.
const providedSignatureBuffer = Buffer.from(signature, 'hex');
const expectedSignatureBuffer = Buffer.from(expectedSignatureHex, 'hex');
// timingSafeEqual throws if buffer lengths differ; guard against that.
if (providedSignatureBuffer.length !== expectedSignatureBuffer.length) {
return false;
}
return crypto.timingSafeEqual(
providedSignatureBuffer,
expectedSignatureBuffer,
);
} catch (error) {
// On any error (e.g., invalid hex in signature), fail closed.
this.logger.warn(
'Failed to verify Linear webhook signature',
error as Error,
);
return false;
}

Copilot uses AI. Check for mistakes.
baseURL: config.get<string>('ai.models.primary.modelUrl'),
},
temperature: 0,
// temperature: 0,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commenting out temperature changes runtime model behavior (and can reduce determinism). If the intent is deterministic outputs for agents/classifiers, set an explicit value instead of leaving a commented line (and remove the extra indentation in the comment).

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +174
const candidates = results
.map((item) => item.value as unknown as MemoryItem)
.filter((memory) => memory.category === 'instruction');

if (candidates.length === 0) {
return null;
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This selects the latest memory with category === 'instruction' but doesn’t scope to the specific record you write (summary = 'Workspace instructions for Linea'). If multiple instruction memories exist in the workspace, this can return the wrong prompt. Filter by both category and the expected summary (or store under a stable key/namespace) to make retrieval unambiguous.

Copilot uses AI. Check for mistakes.

if (linearMatch || slackMatch) {
linkedIdentities.push({
id: `identity-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Date.now() + Math.random() for IDs makes collisions unlikely but still possible, and it’s harder to test/debug. Prefer randomUUID() (Node crypto) for stable uniqueness and consistent formatting.

Copilot uses AI. Check for mistakes.
Comment on lines +356 to +364
async updateInboxStatus(threadId: string, status: string): Promise<void> {
const thread = await this.getThread(threadId);

if (!thread || !thread.isInboxThread) {
this.logger.warn(
`Cannot update inbox status for non-inbox thread: ${threadId}`,
);
return;
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status is typed as string, but the file already imports InboxStatus. Use the union/enum type here so callers can’t write invalid statuses (and so the archive-on-resolution logic is type-checked).

Copilot uses AI. Check for mistakes.
Comment on lines +159 to +163
verifyWebhookSignature(
payload: string,
signature: string,
secret: string,
): boolean {
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The integration library has Jest configured, but this signature verification logic is security-critical and should be unit-tested (valid signature, invalid signature, wrong-length signature, missing/empty signature) to prevent regressions and accidental 500s.

Copilot uses AI. Check for mistakes.
- Adjust type definition for event message handling
- Improve import paths in inbox-messages component
- Optimize GraphQL query and subscription data types
- Update dialog component syntax for consistency
- Introduce TypeScript interfaces for GitHub API responses
- Add TypeScript type assertions to improve type safety
- Modify GraphQL mutations for consistency
- Update UI code for readability and maintainability
Copilot AI review requested due to automatic review settings February 2, 2026 13:37
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 90 out of 160 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +249 to +253
@Body() payload: { prompt?: string },
): Promise<{ prompt: string }> {
if (!payload?.prompt || typeof payload.prompt !== 'string') {
throw new BadRequestException('Prompt is required');
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BadRequestException is used but not imported in this file, which will fail compilation. Add BadRequestException to the @nestjs/common imports at the top of the file.

Copilot uses AI. Check for mistakes.
Comment on lines +129 to +130
const aTime = new Date(a.createdAt || a.updatedAt || 0).getTime();
const bTime = new Date(b.createdAt || b.updatedAt || 0).getTime();
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sorting prioritizes createdAt over updatedAt (createdAt will almost always exist), so recently-updated threads won’t float to the top. Swap the precedence to updatedAt first (updatedAt || createdAt) to reflect recency of activity.

Suggested change
const aTime = new Date(a.createdAt || a.updatedAt || 0).getTime();
const bTime = new Date(b.createdAt || b.updatedAt || 0).getTime();
const aTime = new Date(a.updatedAt || a.createdAt || 0).getTime();
const bTime = new Date(b.updatedAt || b.createdAt || 0).getTime();

Copilot uses AI. Check for mistakes.
return { remoteId: threadId };
}

async updateInboxStatus(threadId: string, status: string): Promise<void> {
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updateInboxStatus accepts an untyped string, but the rest of the code treats inboxStatus as a constrained enum/union (InboxStatus). Accepting arbitrary strings makes it easy to persist invalid states and break filtering/UI. Change the parameter type to InboxStatus (and validate inputs if coming from user/tooling).

Suggested change
async updateInboxStatus(threadId: string, status: string): Promise<void> {
async updateInboxStatus(
threadId: string,
status: InboxStatus,
): Promise<void> {

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +67
const isValid = this.linearService.verifyWebhookSignature(
rawBody,
signature,
this.configService.get('integrations.linear.webhookSecret') as string,
);

if (!isValid) {
this.logger.error(
{ organizationId, integrationId: integrationRecord.id },
'Invalid Linear webhook signature',
);

return { processed: false };
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

integrations.linear.webhookSecret is configured as optional, but this code always verifies the signature and casts the secret to string. If the secret is unset, signature verification will fail (or behave incorrectly) and the webhook will always be rejected. Only verify the signature when a secret is configured; otherwise accept the webhook (or explicitly require a secret and fail fast at startup).

Suggested change
const isValid = this.linearService.verifyWebhookSignature(
rawBody,
signature,
this.configService.get('integrations.linear.webhookSecret') as string,
);
if (!isValid) {
this.logger.error(
{ organizationId, integrationId: integrationRecord.id },
'Invalid Linear webhook signature',
);
return { processed: false };
const webhookSecret = this.configService.get<string>(
'integrations.linear.webhookSecret',
);
if (webhookSecret) {
const isValid = this.linearService.verifyWebhookSignature(
rawBody,
signature,
webhookSecret,
);
if (!isValid) {
this.logger.error(
{ organizationId, integrationId: integrationRecord.id },
'Invalid Linear webhook signature',
);
return { processed: false };
}
} else {
this.logger.warn(
{ organizationId, integrationId: integrationRecord.id },
'Linear webhook secret not configured; skipping signature verification',
);

Copilot uses AI. Check for mistakes.
Comment on lines +146 to +151
private async saveSettingsRecord(
workspaceId: string,
updatedBy: string,
settings: HeartbeatSettings,
existing: HeartbeatSettings | null,
): Promise<void> {
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The saveSettingsRecord method takes an existing parameter but does not use it anywhere. Remove the unused parameter (and corresponding call-site argument) or refactor save/update so the “existing memory record” is passed through to avoid duplicated search/sort work and reduce drift between getSettingsRecord and getSettingsMemory.

Copilot uses AI. Check for mistakes.
await this.store.put(
['filesystem'],
path,
fileData as unknown as Record<string, string>,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fileData is being forced into Record<string, string>, but the public getSkillFiles() return type includes content: string[] (not string). This cast can hide real shape mismatches and lead to runtime incompatibilities for consumers reading from the store. Store the value with an accurate type (e.g., Record<string, unknown>) or normalize/serialize the structure consistently (e.g., content joined to a string) before persisting.

Suggested change
fileData as unknown as Record<string, string>,
fileData as unknown as Record<string, unknown>,

Copilot uses AI. Check for mistakes.
- Refactor import statements for efficiency
- Harmonize LangChain message type handling
- Fix type definition in LaunchlineRuntimeProvider
- Add `BadRequestException` for improved error management
- Ensure consistent use of TypeScript optional chaining
- Format code for better readability and maintainability
Copilot AI review requested due to automatic review settings February 2, 2026 14:05
- Introduce unit test to ensure IntegrationModule is defined
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 91 out of 161 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +249 to +258
@Body() payload: { prompt?: string },
): Promise<{ prompt: string }> {
if (!payload?.prompt || typeof payload.prompt !== 'string') {
throw new BadRequestException('Prompt is required');
}

const trimmedPrompt = payload.prompt.trim();
if (!trimmedPrompt) {
throw new BadRequestException('Prompt cannot be empty');
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BadRequestException is used but not imported from '@nestjs/common' in this file, which will fail compilation. Import BadRequestException alongside the other Nest imports.

Copilot uses AI. Check for mistakes.
Comment on lines 269 to 279
@Get('/thread/:threadId/state')
async getThreadState(
@CurrentUser() currentUser: AuthenticatedUser,
@CurrentWorkspace() workspace: AuthenticatedWorkspace,
@Query('threadId') threadId: string,
): Promise<StateSnapshot> {
const workspace = await this.workspaceFacade.getWorkspaceByUserId(
currentUser.userId,
);

return this.agent.graph.getState({
const agent = await this.agentFactory.getAgentForWorkspace(workspace.id);
return agent.graph.getState({
configurable: {
thread_id: threadId,
workspaceId: workspace.id,
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The route declares :threadId as a path param, but the handler reads it from @query('threadId'). This will break when clients call /thread//state. Switch it to @param('threadId') (and import Param).

Copilot uses AI. Check for mistakes.
Comment on lines 294 to 299
async getThreadState(threadId: string) {
return this.agent.getState({
const agent = await this.agentFactory.getAgentForWorkspace('default');
return agent.getState({
configurable: { thread_id: threadId },
});
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getThreadState() now hardcodes workspaceId = 'default', which will ignore workspace-scoped prompts/skills and can return the wrong state if checkpoints are partitioned by workspaceId in the config. Consider requiring workspaceId as a parameter, or resolving it from the stored thread and calling getAgentForWorkspace(thread.workspaceId).

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +170
const candidates = results
.map((item) => item.value as unknown as MemoryItem)
.filter((memory) => memory.category === 'instruction');
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getPromptMemory filters only by category === 'instruction' and does not scope by a distinct summary/key. If other instruction memories exist in the workspace, this can select the wrong record (latest instruction wins). Consider also filtering by a specific summary (e.g., 'Workspace instructions for Linea') or a dedicated category to avoid collisions.

Copilot uses AI. Check for mistakes.
Comment on lines 22 to 26
apiKey: config.get<string>('ai.models.primary.apiKey'),
baseURL: config.get<string>('ai.models.primary.modelUrl'),
},
temperature: 0,
// temperature: 0,
}),
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commenting out temperature changes model determinism (defaults vary by provider/version) and leaves a stray mis-indented comment in production code. Prefer setting an explicit temperature (even if 0) or removing the commented line entirely.

Copilot uses AI. Check for mistakes.
@dkarasiewicz dkarasiewicz merged commit aebd300 into main Feb 2, 2026
3 of 4 checks passed
@dkarasiewicz dkarasiewicz deleted the feature/lau-31-refine-ui branch February 2, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant