diff --git a/bots/bugbuster/package.json b/bots/bugbuster/package.json index bb0a64d46e0..60711bded6f 100644 --- a/bots/bugbuster/package.json +++ b/bots/bugbuster/package.json @@ -9,8 +9,7 @@ "private": true, "dependencies": { "@botpress/client": "workspace:*", - "@botpress/sdk": "workspace:*", - "@linear/sdk": "^50.0.0" + "@botpress/sdk": "workspace:*" }, "devDependencies": { "@botpress/cli": "workspace:*", diff --git a/bots/bugbuster/src/bootstrap.ts b/bots/bugbuster/src/bootstrap.ts index 01944514669..9d5e23f46fe 100644 --- a/bots/bugbuster/src/bootstrap.ts +++ b/bots/bugbuster/src/bootstrap.ts @@ -10,11 +10,11 @@ export const bootstrap = (props: types.CommonHandlerProps) => { const { client, logger, ctx } = props const botpress = utils.botpress.BotpressApi.create(props) - const linear = utils.linear.LinearApi.create() + const linear = utils.linear.LinearApi.create(client) const teamsManager = new TeamsManager(linear, client, ctx.botId) const recentlyLintedManager = new RecentlyLintedManager(linear) - const issueProcessor = new IssueProcessor(logger, linear, teamsManager) - const issueStateChecker = new IssueStateChecker(linear, logger) + const issueProcessor = new IssueProcessor(logger, linear, teamsManager, ctx.botId) + const issueStateChecker = new IssueStateChecker(linear, logger, ctx.botId) const commandProcessor = new CommandProcessor(client, teamsManager, ctx.botId) return { diff --git a/bots/bugbuster/src/handlers/github-issue-opened.ts b/bots/bugbuster/src/handlers/github-issue-opened.ts index af99d7eb00e..137bfbaea11 100644 --- a/bots/bugbuster/src/handlers/github-issue-opened.ts +++ b/bots/bugbuster/src/handlers/github-issue-opened.ts @@ -1,44 +1,28 @@ import * as boot from '../bootstrap' import * as bp from '.botpress' -const STATE_NAME_FOR_NEW_ISSUES = 'Triage' -const TEAM_KEY_FOR_NEW_ISSUES = 'ENG' +const TEAM_NAME_FOR_NEW_ISSUES = 'Engineering' export const handleGithubIssueOpened: bp.EventHandlers['github:issueOpened'] = async (props): Promise => { const githubIssue = props.event.payload props.logger.info('Received GitHub issue', githubIssue) - const { linear, botpress } = boot.bootstrap(props) + const { botpress, linear } = boot.bootstrap(props) const _handleError = (context: string) => (thrown: unknown): Promise => botpress.handleError({ context, conversationId: undefined }, thrown) - const teamStates = await linear - .findTeamStates(TEAM_KEY_FOR_NEW_ISSUES) - .catch(_handleError('trying to get Linear team states')) - - if (!teamStates) { - props.logger.error(`Error: Linear team '${TEAM_KEY_FOR_NEW_ISSUES}' not found.`) - return - } - - const state = teamStates.states.nodes.find((el) => el.name === STATE_NAME_FOR_NEW_ISSUES) - - if (!state) { - props.logger.error(`Error: Linear state '${STATE_NAME_FOR_NEW_ISSUES}' not found.`) - return - } - - const linearResponse = await linear.client - .createIssue({ - teamId: teamStates.id, - stateId: state.id, - title: githubIssue.issue.name, - description: githubIssue.issue.body, - labelIds: [], + const linearResponse = await props.client + .callAction({ + type: 'linear:createIssue', + input: { + teamName: TEAM_NAME_FOR_NEW_ISSUES, + description: githubIssue.issue.body, + title: githubIssue.issue.name, + }, }) .catch(_handleError('trying to create a Linear issue from the GitHub issue')) @@ -48,10 +32,11 @@ export const handleGithubIssueOpened: bp.EventHandlers['github:issueOpened'] = a `GitHub Issue: [${githubIssue.issue.name}](${githubIssue.issue.url})`, ].join('\n') - await linear.client + await linear .createComment({ - issueId: linearResponse.issueId, body: comment, + issueId: linearResponse.output.issue.id, + botId: props.ctx.botId, }) .catch(_handleError('trying to create a comment on the Linear issue created from GitHub')) } diff --git a/bots/bugbuster/src/handlers/message-created.ts b/bots/bugbuster/src/handlers/message-created.ts index dbf67cf4035..74693b9315b 100644 --- a/bots/bugbuster/src/handlers/message-created.ts +++ b/bots/bugbuster/src/handlers/message-created.ts @@ -67,7 +67,7 @@ const _buildListCommandsMessage = (definitions: CommandDefinition[]) => { } const _buildCommandMessage = (definition: CommandDefinition) => { - const requiredArgs = definition.requiredArgs?.map((arg) => `<${arg}>`).join(' ') + const requiredArgs = definition.requiredArgs?.map((arg) => `<${arg}>`).join(' ') const optionalArgs = definition.optionalArgs?.map((arg) => `[${arg}]`).join(' ') return `${definition.name} ${requiredArgs ?? ''} ${optionalArgs ?? ''}` diff --git a/bots/bugbuster/src/services/issue-processor/index.ts b/bots/bugbuster/src/services/issue-processor/index.ts index bdffca0ec68..c713118fb42 100644 --- a/bots/bugbuster/src/services/issue-processor/index.ts +++ b/bots/bugbuster/src/services/issue-processor/index.ts @@ -11,7 +11,8 @@ export class IssueProcessor { public constructor( private _logger: sdk.BotLogger, private _linear: lin.LinearApi, - private _teamsManager: tm.TeamsManager + private _teamsManager: tm.TeamsManager, + private _botId: string ) {} /** @@ -75,8 +76,9 @@ export class IssueProcessor { this._logger.warn(warningMessage) - await this._linear.client.createComment({ + await this._linear.createComment({ issueId: issue.id, + botId: this._botId, body: [ `BugBuster Bot found the following problems with ${issue.identifier}:`, '', diff --git a/bots/bugbuster/src/services/issue-state-checker.ts b/bots/bugbuster/src/services/issue-state-checker.ts index 62fdec3397e..9d0fdcf933b 100644 --- a/bots/bugbuster/src/services/issue-state-checker.ts +++ b/bots/bugbuster/src/services/issue-state-checker.ts @@ -5,7 +5,8 @@ import * as lin from '../utils/linear-utils' export class IssueStateChecker { public constructor( private _linear: lin.LinearApi, - private _logger: sdk.BotLogger + private _logger: sdk.BotLogger, + private _botId: string ) {} public async processIssues(props: { stateAttributes: types.StateAttributes; teams: string[] }) { @@ -24,8 +25,9 @@ export class IssueStateChecker { ) for (const issue of issues) { - await this._linear.client.createComment({ + await this._linear.createComment({ issueId: issue.id, + botId: this._botId, body: stateAttributes.warningComment, }) this._logger.warn(stateAttributes.buildWarningReason(issue.identifier)) diff --git a/bots/bugbuster/src/services/recently-linted-manager.ts b/bots/bugbuster/src/services/recently-linted-manager.ts index 351268751e8..f9023376bfc 100644 --- a/bots/bugbuster/src/services/recently-linted-manager.ts +++ b/bots/bugbuster/src/services/recently-linted-manager.ts @@ -6,9 +6,9 @@ export class RecentlyLintedManager { public constructor(private _linear: lin.LinearApi) {} public async isRecentlyLinted(issue: lin.Issue): Promise { - const me = await this._linear.getMe() + const me = await this._linear.getViewerId() const timestamps = issue.comments.nodes - .filter((comment) => comment.user?.id === me.id) + .filter((comment) => comment.user?.id === me) .map((comment) => new Date(comment.createdAt).getTime()) const now = new Date().getTime() for (const timestamp of timestamps) { diff --git a/bots/bugbuster/src/types.ts b/bots/bugbuster/src/types.ts index e06d45581b3..f55855fc47a 100644 --- a/bots/bugbuster/src/types.ts +++ b/bots/bugbuster/src/types.ts @@ -33,6 +33,19 @@ export type StateAttributes = { buildWarningReason: (issueIdentifier: string) => string } +export type LinearTeam = { + id: string + key: string + name: string + description?: string | undefined + icon?: string | undefined +} + +export type LinearState = { + id: string + name: string +} + export type ISO8601Duration = string type CommandResult = { success: boolean; message: string } diff --git a/bots/bugbuster/src/utils/linear-utils/client.ts b/bots/bugbuster/src/utils/linear-utils/client.ts index 5fcda04806e..d0fc27e1e47 100644 --- a/bots/bugbuster/src/utils/linear-utils/client.ts +++ b/bots/bugbuster/src/utils/linear-utils/client.ts @@ -1,40 +1,36 @@ -import * as lin from '@linear/sdk' import * as utils from '..' -import * as genenv from '../../../.genenv' import * as types from '../../types' import * as graphql from './graphql-queries' +import { Client } from '.botpress' -type State = { state: lin.WorkflowState; key: types.StateKey } +type State = { state: types.LinearState; key: types.StateKey } const RESULTS_PER_PAGE = 200 export class LinearApi { - private _teams?: lin.Team[] = undefined + private _teams?: types.LinearTeam[] = undefined private _states?: State[] = undefined - private _viewer?: lin.User = undefined + private _viewerId?: string = undefined - private constructor(private _client: lin.LinearClient) {} + private constructor(private _bpClient: Client) {} - public static create(): LinearApi { - const client = new lin.LinearClient({ apiKey: genenv.BUGBUSTER_LINEAR_API_KEY }) - - return new LinearApi(client) - } - - public get client(): lin.LinearClient { - return this._client + public static create(bpClient: Client): LinearApi { + return new LinearApi(bpClient) } - public async getMe(): Promise { - if (this._viewer) { - return this._viewer + public async getViewerId(): Promise { + if (this._viewerId) { + return this._viewerId } - const me = await this._client.viewer + const { output: me } = await this._bpClient.callAction({ + type: 'linear:getUser', + input: {}, + }) if (!me) { throw new Error('Viewer not found. Please ensure you are authenticated.') } - this._viewer = me - return this._viewer + this._viewerId = me.linearId + return this._viewerId } public async isTeam(teamKey: string) { @@ -95,19 +91,6 @@ export class LinearApi { return { issues: data.issues.nodes, pagination: data.pageInfo } } - public async findLabel(filter: { name: string; parentName?: string }): Promise { - const { name, parentName } = filter - const { nodes: labels } = await this._client.issueLabels({ - filter: { - name: { eq: name }, - parent: parentName ? { name: { eq: parentName } } : undefined, - }, - }) - - const [label] = labels - return label || undefined - } - public async issueState(issue: graphql.Issue): Promise { const states = await this.getStates() const state = states.find((s) => s.state.id === issue.state.id) @@ -119,17 +102,35 @@ export class LinearApi { public async resolveComments(issue: graphql.Issue): Promise { const comments = issue.comments.nodes - const me = await this.getMe() + const me = await this.getViewerId() - const promises: Promise[] = [] + const promises: ReturnType>[] = [] for (const comment of comments) { - if (comment.user?.id === me.id && !comment.parentId && !comment.resolvedAt) { - promises.push(this._client.commentResolve(comment.id)) + if (comment.user?.id === me && !comment.parentId && !comment.resolvedAt) { + promises.push(this._bpClient.callAction({ type: 'linear:resolveComment', input: { id: comment.id } })) } } await Promise.all(promises) } + public async createComment(props: { body: string; issueId: string; botId: string }): Promise { + const { body, issueId, botId } = props + const conversation = await this._bpClient.callAction({ + type: 'linear:getOrCreateIssueConversation', + input: { + conversation: { id: issueId }, + }, + }) + + await this._bpClient.createMessage({ + type: 'text', + conversationId: conversation.output.conversationId, + payload: { text: body }, + tags: {}, + userId: botId, + }) + } + public async findTeamStates(teamKey: string): Promise { const queryInput: graphql.GRAPHQL_QUERIES['findTeamStates'][graphql.QUERY_INPUT] = { filter: { key: { eq: teamKey } }, @@ -144,7 +145,7 @@ export class LinearApi { return team } - public async getTeams(): Promise { + public async getTeams(): Promise { if (!this._teams) { this._teams = await this._listAllTeams() } @@ -170,29 +171,31 @@ export class LinearApi { }) } - private _listAllTeams = async (): Promise => { - let teams: lin.Team[] = [] - let cursor: string | undefined = undefined - do { - const response = await this._client.teams({ after: cursor, first: 100 }) - teams = teams.concat(response.nodes) - cursor = response.pageInfo.endCursor - } while (cursor) - return teams - } - - private _listAllStates = async (): Promise => { - let states: lin.WorkflowState[] = [] - let cursor: string | undefined = undefined - do { - const response = await this._client.workflowStates({ after: cursor, first: 100 }) - states = states.concat(response.nodes) - cursor = response.pageInfo.endCursor - } while (cursor) + private _listAllTeams = async (): Promise => { + const response = await this._bpClient.callAction({ type: 'linear:listTeams', input: {} }) + return response.output.teams + } + + private _listAllStates = async (): Promise => { + let response = await this._bpClient.callAction<'linear:listStates'>({ + type: 'linear:listStates', + input: { count: 100 }, + }) + let states: types.LinearState[] = response.output.states + let startCursor = response.output.nextCursor + + while (startCursor) { + response = await this._bpClient.callAction<'linear:listStates'>({ + type: 'linear:listStates', + input: { count: 100, startCursor }, + }) + states = states.concat(response.output.states) + startCursor = response.output.nextCursor + } return states } - private static _toStateObjects(states: lin.WorkflowState[]): State[] { + private static _toStateObjects(states: types.LinearState[]): State[] { const stateObjects: State[] = [] for (const state of states) { const key = utils.string.toScreamingSnakeCase(state.name) as types.StateKey @@ -205,7 +208,17 @@ export class LinearApi { queryName: K, variables: graphql.GRAPHQL_QUERIES[K][graphql.QUERY_INPUT] ): Promise { - return (await this._client.client.rawRequest(graphql.GRAPHQL_QUERIES[queryName].query, variables)) - .data as graphql.GRAPHQL_QUERIES[K][graphql.QUERY_RESPONSE] + const params = Object.entries(variables).map(([name, value]) => ({ + name, + value, + })) + const result = await this._bpClient.callAction({ + type: 'linear:sendRawGraphqlQuery', + input: { + query: graphql.GRAPHQL_QUERIES[queryName].query, + parameters: params, + }, + }) + return result.output.result as graphql.GRAPHQL_QUERIES[K][graphql.QUERY_RESPONSE] } } diff --git a/packages/cli/package.json b/packages/cli/package.json index 10fd6d7ac6e..439d46f3cc3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -28,7 +28,7 @@ "@apidevtools/json-schema-ref-parser": "^11.7.0", "@botpress/chat": "0.5.4", "@botpress/client": "1.29.0", - "@botpress/sdk": "5.2.0", + "@botpress/sdk": "5.3.0", "@bpinternal/const": "^0.1.0", "@bpinternal/tunnel": "^0.1.1", "@bpinternal/verel": "^0.2.0", diff --git a/packages/cli/templates/empty-bot/package.json b/packages/cli/templates/empty-bot/package.json index df80c5e474d..43cb860605e 100644 --- a/packages/cli/templates/empty-bot/package.json +++ b/packages/cli/templates/empty-bot/package.json @@ -6,7 +6,7 @@ "private": true, "dependencies": { "@botpress/client": "1.29.0", - "@botpress/sdk": "5.2.0" + "@botpress/sdk": "5.3.0" }, "devDependencies": { "@types/node": "^22.16.4", diff --git a/packages/cli/templates/empty-integration/package.json b/packages/cli/templates/empty-integration/package.json index 368f7b08e18..1bad78af503 100644 --- a/packages/cli/templates/empty-integration/package.json +++ b/packages/cli/templates/empty-integration/package.json @@ -7,7 +7,7 @@ "private": true, "dependencies": { "@botpress/client": "1.29.0", - "@botpress/sdk": "5.2.0" + "@botpress/sdk": "5.3.0" }, "devDependencies": { "@types/node": "^22.16.4", diff --git a/packages/cli/templates/empty-plugin/package.json b/packages/cli/templates/empty-plugin/package.json index 7c90bd4eda8..8fc3e8e0e00 100644 --- a/packages/cli/templates/empty-plugin/package.json +++ b/packages/cli/templates/empty-plugin/package.json @@ -6,7 +6,7 @@ }, "private": true, "dependencies": { - "@botpress/sdk": "5.2.0" + "@botpress/sdk": "5.3.0" }, "devDependencies": { "@types/node": "^22.16.4", diff --git a/packages/cli/templates/hello-world/package.json b/packages/cli/templates/hello-world/package.json index 43a263bac37..cab4048b05c 100644 --- a/packages/cli/templates/hello-world/package.json +++ b/packages/cli/templates/hello-world/package.json @@ -7,7 +7,7 @@ "private": true, "dependencies": { "@botpress/client": "1.29.0", - "@botpress/sdk": "5.2.0" + "@botpress/sdk": "5.3.0" }, "devDependencies": { "@types/node": "^22.16.4", diff --git a/packages/cli/templates/webhook-message/package.json b/packages/cli/templates/webhook-message/package.json index d19df6af266..25ec09da92e 100644 --- a/packages/cli/templates/webhook-message/package.json +++ b/packages/cli/templates/webhook-message/package.json @@ -7,7 +7,7 @@ "private": true, "dependencies": { "@botpress/client": "1.29.0", - "@botpress/sdk": "5.2.0", + "@botpress/sdk": "5.3.0", "axios": "^1.6.8" }, "devDependencies": { diff --git a/packages/llmz/package.json b/packages/llmz/package.json index 2284d246910..6546f2e850d 100644 --- a/packages/llmz/package.json +++ b/packages/llmz/package.json @@ -2,7 +2,7 @@ "name": "llmz", "type": "module", "description": "LLMz - An LLM-native Typescript VM built on top of Zui", - "version": "0.0.42", + "version": "0.0.43", "types": "./dist/index.d.ts", "main": "./dist/index.cjs", "module": "./dist/index.js", diff --git a/packages/llmz/src/llmz.test.ts b/packages/llmz/src/llmz.test.ts new file mode 100644 index 00000000000..4e00c41977e --- /dev/null +++ b/packages/llmz/src/llmz.test.ts @@ -0,0 +1,41 @@ +import { Client } from '@botpress/client' +import { Cognitive, Model } from '@botpress/cognitive' +import { expect, test } from 'vitest' +import { executeContext } from './llmz.js' +import { ErrorExecutionResult } from './result.js' +import { CognitiveError } from './errors.js' + +test('executeContext should early exit when cognitive service is unreachable', async () => { + class FailingCognitive extends Cognitive { + public constructor(private _err: Error) { + super({ client: new Client({}) }) + } + + public async getModelDetails(model: string): Promise { + return { + id: model, + name: 'Failing Cognitive Model', + integration: 'botpress', + description: 'A failing cognitive model that simulates errors', + input: { maxTokens: 8192, costPer1MTokens: 0 }, + output: { maxTokens: 2048, costPer1MTokens: 0 }, + ref: `failing:${model}`, + tags: [], + } + } + + public async generateContent(): Promise { + throw this._err + } + } + + const err = new Error('Simulated connection error') + const cognitive = new FailingCognitive(err) + + const output = await executeContext({ client: cognitive, options: { loop: 5 } }) + + expect(output.status).toBe('error') + expect(output.iterations.length).toBe(1) + expect((output as ErrorExecutionResult).error).toBeInstanceOf(CognitiveError) + expect(((output as ErrorExecutionResult).error as Error).message).toContain(err.message) +}) diff --git a/packages/llmz/src/llmz.ts b/packages/llmz/src/llmz.ts index 5be15836e5c..7883a6c3250 100644 --- a/packages/llmz/src/llmz.ts +++ b/packages/llmz/src/llmz.ts @@ -341,7 +341,11 @@ export const _executeContext = async (props: ExecutionProps): Promise => { let startedAt = Date.now() const traces = iteration.traces - const model = await cognitive.getModelDetails(Array.isArray(iteration.model) ? iteration.model[0]! : iteration.model) + + const modelRef = Array.isArray(iteration.model) ? iteration.model[0]! : iteration.model + const model = await cognitive.getModelDetails(modelRef).catch((thrown) => { + throw new CognitiveError(`Failed to fetch model details for model "${modelRef}": ${getErrorMessage(thrown)}`) + }) const modelLimit = Math.max(model.input.maxTokens, 8_000) const responseLengthBuffer = getModelOutputLimit(modelLimit) @@ -439,15 +447,19 @@ const executeIteration = async ({ model: model.ref, }) - const output = await cognitive.generateContent({ - signal: controller.signal, - systemPrompt: messages.find((x) => x.role === 'system')?.content, - model: model.ref, - temperature: iteration.temperature, - responseFormat: 'text', - messages: messages.filter((x) => x.role !== 'system'), - stopSequences: ctx.version.getStopTokens(), - }) + const output = await cognitive + .generateContent({ + signal: controller.signal, + systemPrompt: messages.find((x) => x.role === 'system')?.content, + model: model.ref, + temperature: iteration.temperature, + responseFormat: 'text', + messages: messages.filter((x) => x.role !== 'system'), + stopSequences: ctx.version.getStopTokens(), + }) + .catch((thrown) => { + throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`) + }) const out = typeof output.output.choices?.[0]?.content === 'string' ? output.output.choices[0].content : null diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 272348fdb68..c4e44443548 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@botpress/sdk", - "version": "5.2.0", + "version": "5.3.0", "description": "Botpress SDK", "main": "./dist/index.cjs", "module": "./dist/index.mjs", diff --git a/packages/sdk/src/base-logger.ts b/packages/sdk/src/base-logger.ts index 7afcb47cddb..f0b1819c1ea 100644 --- a/packages/sdk/src/base-logger.ts +++ b/packages/sdk/src/base-logger.ts @@ -2,6 +2,18 @@ import util from 'util' type LogLevel = 'info' | 'debug' | 'warn' | 'error' +export type IssueLogEvent = { + type: 'issue' + code: string + category: 'user_code' | 'limits' | 'configuration' | 'other' + title: string + description: string + data: Record + /** This groups by data fields */ + groupBy: string[] + traceId?: string +} + export abstract class BaseLogger { protected defaultOptions: TOptions @@ -27,6 +39,10 @@ export abstract class BaseLogger { this._log('error', args) } + public issue(args: IssueLogEvent) { + console.info(JSON.stringify(args)) + } + private _log(level: LogLevel, args: Parameters) { this._getConsoleMethod(level)(this._serializeMessage(args)) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5ff398c0a3..0b7374b877e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,9 +118,6 @@ importers: '@botpress/sdk': specifier: workspace:* version: link:../../packages/sdk - '@linear/sdk': - specifier: ^50.0.0 - version: 50.0.0 devDependencies: '@botpress/cli': specifier: workspace:* @@ -2501,7 +2498,7 @@ importers: specifier: 1.29.0 version: link:../client '@botpress/sdk': - specifier: 5.2.0 + specifier: 5.3.0 version: link:../sdk '@bpinternal/const': specifier: ^0.1.0 @@ -2625,7 +2622,7 @@ importers: specifier: 1.29.0 version: link:../../../client '@botpress/sdk': - specifier: 5.2.0 + specifier: 5.3.0 version: link:../../../sdk devDependencies: '@types/node': @@ -2641,7 +2638,7 @@ importers: specifier: 1.29.0 version: link:../../../client '@botpress/sdk': - specifier: 5.2.0 + specifier: 5.3.0 version: link:../../../sdk devDependencies: '@types/node': @@ -2654,7 +2651,7 @@ importers: packages/cli/templates/empty-plugin: dependencies: '@botpress/sdk': - specifier: 5.2.0 + specifier: 5.3.0 version: link:../../../sdk devDependencies: '@types/node': @@ -2670,7 +2667,7 @@ importers: specifier: 1.29.0 version: link:../../../client '@botpress/sdk': - specifier: 5.2.0 + specifier: 5.3.0 version: link:../../../sdk devDependencies: '@types/node': @@ -2686,7 +2683,7 @@ importers: specifier: 1.29.0 version: link:../../../client '@botpress/sdk': - specifier: 5.2.0 + specifier: 5.3.0 version: link:../../../sdk axios: specifier: ^1.6.8 @@ -4961,10 +4958,6 @@ packages: resolution: {integrity: sha512-PPtul1vzoyZ5HkNqh643YD0TCFqOHI6ld4x69c/prwAxornBxPaeXoHbHcFeK8gaD2W4/666mPQe5K3CmUMepw==} engines: {node: '>=18'} - '@linear/sdk@50.0.0': - resolution: {integrity: sha512-cqOTIkayqCDTBITCieuZ3acMiJmWZB0bR9FhfrfMs2B5PotntDgcfNCBW+21LcMwcBrq0A84kwK2AQzdu+Atsg==} - engines: {node: '>=12.x', yarn: 1.x} - '@linear/sdk@55.2.1': resolution: {integrity: sha512-0+xjyphwdMMeGIV5O1Q7/AhS/tyTv+J0azE/WPbVXJHCDkBdgoHERvBgNXM0nRjcVt2RKUl8V0o+Fly2CJRlOA==} engines: {node: '>=12.x', yarn: 1.x} @@ -14047,14 +14040,6 @@ snapshots: transitivePeerDependencies: - debug - '@linear/sdk@50.0.0': - dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@15.8.0) - graphql: 15.8.0 - isomorphic-unfetch: 3.1.0 - transitivePeerDependencies: - - encoding - '@linear/sdk@55.2.1': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@15.8.0)