From 270a017aa61bcee8ed7b01052d6e265aea0ca6d7 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Wed, 22 May 2024 19:08:53 +0100 Subject: [PATCH 01/27] feat(gendo): scaffolding --- packages/server/modules/gendo/index.ts | 12 ++++++++++++ packages/server/modules/index.js | 3 ++- packages/shared/src/environment/index.ts | 3 ++- 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 packages/server/modules/gendo/index.ts diff --git a/packages/server/modules/gendo/index.ts b/packages/server/modules/gendo/index.ts new file mode 100644 index 0000000000..4cc4da6c42 --- /dev/null +++ b/packages/server/modules/gendo/index.ts @@ -0,0 +1,12 @@ +import { SpeckleModule } from '@/modules/shared/helpers/typeHelper' +import { moduleLogger } from '@/logging/logging' + +export = { + async init() { + moduleLogger.info('🪞 Init Gendo AI render module') + // TODO + }, + async shutdown() { + // TODO + } +} as SpeckleModule diff --git a/packages/server/modules/index.js b/packages/server/modules/index.js index ef6178efe7..6878a3d9e2 100644 --- a/packages/server/modules/index.js +++ b/packages/server/modules/index.js @@ -42,7 +42,7 @@ function autoloadFromDirectory(dirPath) { } const getEnabledModuleNames = () => { - const { FF_AUTOMATE_MODULE_ENABLED } = Environment.getFeatureFlags() + const { FF_AUTOMATE_MODULE_ENABLED, FF_GENDOAI_MODULE_ENABLED } = Environment.getFeatureFlags() const moduleNames = [ 'accessrequests', 'activitystream', @@ -64,6 +64,7 @@ const getEnabledModuleNames = () => { ] if (FF_AUTOMATE_MODULE_ENABLED) moduleNames.push('automate') + if (FF_GENDOAI_MODULE_ENABLED) moduleNames.push('gendo') return moduleNames } diff --git a/packages/shared/src/environment/index.ts b/packages/shared/src/environment/index.ts index f5813675d3..95e49b89eb 100644 --- a/packages/shared/src/environment/index.ts +++ b/packages/shared/src/environment/index.ts @@ -4,7 +4,8 @@ import { z } from 'zod' //INFO // As a convention all feature flags should be prefixed with a FF_ const featureFlagSchema = z.object({ - FF_AUTOMATE_MODULE_ENABLED: z.boolean().default(false) + FF_AUTOMATE_MODULE_ENABLED: z.boolean().default(false), + FF_GENDOAI_MODULE_ENABLED: z.boolean().default(false) }) function parseFeatureFlags() { From 687538a89a87ebb4a151522aa3044e5daf358352 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Thu, 23 May 2024 13:31:53 +0100 Subject: [PATCH 02/27] feat(gendo): wip --- .../frontend-2/assets/images/gendo/logo.svg | 4 ++ .../frontend-2/components/viewer/Controls.vue | 28 ++++++++- .../components/viewer/gendo/Panel.vue | 39 ++++++++++++ packages/frontend-2/composables/globals.ts | 7 +++ .../lib/common/generated/gql/graphql.ts | 34 +++++++++++ .../assets/gendo/typedefs/gendo.graphql | 36 +++++++++++ packages/server/modules/core/dbSchema.ts | 14 +++++ .../modules/core/graph/generated/graphql.ts | 61 +++++++++++++++++++ .../graph/generated/graphql.ts | 34 +++++++++++ .../modules/gendo/graph/resolvers/index.ts | 30 +++++++++ .../modules/gendo/helpers/types/index.ts | 13 ++++ .../gendo/migrations/20240522130000_gendo.ts | 39 ++++++++++++ .../server/modules/gendo/services/index.ts | 29 +++++++++ .../modules/shared/helpers/envHelper.ts | 4 ++ .../server/test/graphql/generated/graphql.ts | 34 +++++++++++ 15 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 packages/frontend-2/assets/images/gendo/logo.svg create mode 100644 packages/frontend-2/components/viewer/gendo/Panel.vue create mode 100644 packages/server/assets/gendo/typedefs/gendo.graphql create mode 100644 packages/server/modules/gendo/graph/resolvers/index.ts create mode 100644 packages/server/modules/gendo/helpers/types/index.ts create mode 100644 packages/server/modules/gendo/migrations/20240522130000_gendo.ts create mode 100644 packages/server/modules/gendo/services/index.ts diff --git a/packages/frontend-2/assets/images/gendo/logo.svg b/packages/frontend-2/assets/images/gendo/logo.svg new file mode 100644 index 0000000000..e0a6fe01cd --- /dev/null +++ b/packages/frontend-2/assets/images/gendo/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/frontend-2/components/viewer/Controls.vue b/packages/frontend-2/components/viewer/Controls.vue index 40b3a4a162..a256d4b021 100644 --- a/packages/frontend-2/components/viewer/Controls.vue +++ b/packages/frontend-2/components/viewer/Controls.vue @@ -137,13 +137,28 @@ + + + + gendo Logo +
+
+ +
@@ -237,6 +259,9 @@ import { useViewerTour } from '~/lib/viewer/composables/tour' import { onKeyStroke } from '@vueuse/core' import { useFunctionRunsStatusSummary } from '~/lib/automate/composables/runStatus' +// const isGendoEnabled = useIsAutomateModuleEnabled() // Not working for some reason, always false +const isGendoEnabled = ref(true) + type ActiveControl = | 'none' | 'models' @@ -246,6 +271,7 @@ type ActiveControl = | 'automate' | 'measurements' | 'mobileOverflow' + | 'gendo' const { resourceItems, modelsAndVersionIds } = useInjectedViewerLoadedResources() const { toggleSectionBox, isSectionBoxEnabled } = useSectionBoxUtilities() diff --git a/packages/frontend-2/components/viewer/gendo/Panel.vue b/packages/frontend-2/components/viewer/gendo/Panel.vue new file mode 100644 index 0000000000..3487221c42 --- /dev/null +++ b/packages/frontend-2/components/viewer/gendo/Panel.vue @@ -0,0 +1,39 @@ + + diff --git a/packages/frontend-2/composables/globals.ts b/packages/frontend-2/composables/globals.ts index 01b9481122..27c8ab283a 100644 --- a/packages/frontend-2/composables/globals.ts +++ b/packages/frontend-2/composables/globals.ts @@ -9,4 +9,11 @@ export const useIsAutomateModuleEnabled = () => { return ref(FF_AUTOMATE_MODULE_ENABLED) } +export const useIsGendoModuleEnabled = () => { + const { + public: { FF_GENDOAI_MODULE_ENABLED } + } = useRuntimeConfig() + return ref(FF_GENDOAI_MODULE_ENABLED) +} + export { useGlobalToast, useActiveUser } diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index 8a64a5431e..b3f78e877a 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -939,6 +939,33 @@ export type FunctionRunStatusInput = { statusMessage?: InputMaybe; }; +export type GendoAiRender = { + __typename?: 'GendoAIRender'; + cameraLocation?: Maybe; + createdAt: Scalars['String']; + gendoGenerationId?: Maybe; + id: Scalars['ID']; + prompt: Scalars['String']; + status: Scalars['String']; + updatedAt: Scalars['String']; +}; + +export type GendoAiRenderCollection = { + __typename?: 'GendoAIRenderCollection'; + items: Array; + totalCount: Scalars['Int']; +}; + +export type GendoAiRenderInput = { + /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ + baseImage: Scalars['String']; + modelId: Scalars['ID']; + projectId: Scalars['ID']; + /** The generation prompt. */ + prompt: Scalars['String']; + versionId: Scalars['ID']; +}; + export type LegacyCommentViewerData = { __typename?: 'LegacyCommentViewerData'; /** @@ -3204,6 +3231,7 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; + gendoAIRenders?: Maybe; id: Scalars['ID']; message?: Maybe; model: Model; @@ -3244,6 +3272,7 @@ export type VersionMutations = { __typename?: 'VersionMutations'; delete: Scalars['Boolean']; moveToModel: Model; + requestGendoAIRender: Scalars['Boolean']; update: Version; }; @@ -3258,6 +3287,11 @@ export type VersionMutationsMoveToModelArgs = { }; +export type VersionMutationsRequestGendoAiRenderArgs = { + input?: InputMaybe; +}; + + export type VersionMutationsUpdateArgs = { input: UpdateVersionInput; }; diff --git a/packages/server/assets/gendo/typedefs/gendo.graphql b/packages/server/assets/gendo/typedefs/gendo.graphql new file mode 100644 index 0000000000..9dd5b7e461 --- /dev/null +++ b/packages/server/assets/gendo/typedefs/gendo.graphql @@ -0,0 +1,36 @@ +extend type Version { + gendoAIRenders: GendoAIRenderCollection +} + +type GendoAIRenderCollection { + totalCount: Int! + items: [GendoAIRender!]! +} + +type GendoAIRender { + id: ID! + createdAt: String! + updatedAt: String! + gendoGenerationId: String + status: String! + prompt: String! + cameraLocation: JSONObject +} + +extend type VersionMutations { + requestGendoAIRender(input: GendoAIRenderInput): Boolean! +} + +input GendoAIRenderInput { + projectId: ID! + modelId: ID! + versionId: ID! + """ + The generation prompt. + """ + prompt: String! + """ + Base64 encoded image of the depthmap, resized to 1024 on the longest size. + """ + baseImage: String! +} diff --git a/packages/server/modules/core/dbSchema.ts b/packages/server/modules/core/dbSchema.ts index 74da26edf4..842b01aca1 100644 --- a/packages/server/modules/core/dbSchema.ts +++ b/packages/server/modules/core/dbSchema.ts @@ -632,4 +632,18 @@ export const Automations = buildTableHelper('automations', [ 'executionEngineAutomationId' ]) +export const GendoAIRenders = buildTableHelper('gendo_ai_renders', [ + 'id', + 'userId', + 'versionId', + 'createdAt', + 'updatedAt', + 'gendoGenerationId', + 'status', + 'prompt', + 'cameraLocation', + 'baseImage', + 'responseImage' +]) + export { knex } diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index 4f737bb481..6a49454553 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -953,6 +953,33 @@ export type FunctionRunStatusInput = { statusMessage?: InputMaybe; }; +export type GendoAiRender = { + __typename?: 'GendoAIRender'; + cameraLocation?: Maybe; + createdAt: Scalars['String']; + gendoGenerationId?: Maybe; + id: Scalars['ID']; + prompt: Scalars['String']; + status: Scalars['String']; + updatedAt: Scalars['String']; +}; + +export type GendoAiRenderCollection = { + __typename?: 'GendoAIRenderCollection'; + items: Array; + totalCount: Scalars['Int']; +}; + +export type GendoAiRenderInput = { + /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ + baseImage: Scalars['String']; + modelId: Scalars['ID']; + projectId: Scalars['ID']; + /** The generation prompt. */ + prompt: Scalars['String']; + versionId: Scalars['ID']; +}; + export type LegacyCommentViewerData = { __typename?: 'LegacyCommentViewerData'; /** @@ -3218,6 +3245,7 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; + gendoAIRenders?: Maybe; id: Scalars['ID']; message?: Maybe; model: Model; @@ -3258,6 +3286,7 @@ export type VersionMutations = { __typename?: 'VersionMutations'; delete: Scalars['Boolean']; moveToModel: Model; + requestGendoAIRender: Scalars['Boolean']; update: Version; }; @@ -3272,6 +3301,11 @@ export type VersionMutationsMoveToModelArgs = { }; +export type VersionMutationsRequestGendoAiRenderArgs = { + input?: InputMaybe; +}; + + export type VersionMutationsUpdateArgs = { input: UpdateVersionInput; }; @@ -3556,6 +3590,9 @@ export type ResolversTypes = { FileUpload: ResolverTypeWrapper; Float: ResolverTypeWrapper; FunctionRunStatusInput: FunctionRunStatusInput; + GendoAIRender: ResolverTypeWrapper; + GendoAIRenderCollection: ResolverTypeWrapper; + GendoAIRenderInput: GendoAiRenderInput; ID: ResolverTypeWrapper; Int: ResolverTypeWrapper; JSONObject: ResolverTypeWrapper; @@ -3769,6 +3806,9 @@ export type ResolversParentTypes = { FileUpload: FileUploadGraphQLReturn; Float: Scalars['Float']; FunctionRunStatusInput: FunctionRunStatusInput; + GendoAIRender: GendoAiRender; + GendoAIRenderCollection: GendoAiRenderCollection; + GendoAIRenderInput: GendoAiRenderInput; ID: Scalars['ID']; Int: Scalars['Int']; JSONObject: Scalars['JSONObject']; @@ -4355,6 +4395,23 @@ export type FileUploadResolvers; }; +export type GendoAiRenderResolvers = { + cameraLocation?: Resolver, ParentType, ContextType>; + createdAt?: Resolver; + gendoGenerationId?: Resolver, ParentType, ContextType>; + id?: Resolver; + prompt?: Resolver; + status?: Resolver; + updatedAt?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + +export type GendoAiRenderCollectionResolvers = { + items?: Resolver, ParentType, ContextType>; + totalCount?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export interface JsonObjectScalarConfig extends GraphQLScalarTypeConfig { name: 'JSONObject'; } @@ -5016,6 +5073,7 @@ export type VersionResolvers, ParentType, ContextType>; commentThreads?: Resolver>; createdAt?: Resolver; + gendoAIRenders?: Resolver, ParentType, ContextType>; id?: Resolver; message?: Resolver, ParentType, ContextType>; model?: Resolver; @@ -5050,6 +5108,7 @@ export type VersionCreatedTriggerDefinitionResolvers = { delete?: Resolver>; moveToModel?: Resolver>; + requestGendoAIRender?: Resolver>; update?: Resolver>; __isTypeOf?: IsTypeOfResolverFn; }; @@ -5164,6 +5223,8 @@ export type Resolvers = { DateTime?: GraphQLScalarType; EmailAddress?: GraphQLScalarType; FileUpload?: FileUploadResolvers; + GendoAIRender?: GendoAiRenderResolvers; + GendoAIRenderCollection?: GendoAiRenderCollectionResolvers; JSONObject?: GraphQLScalarType; LegacyCommentViewerData?: LegacyCommentViewerDataResolvers; LimitedUser?: LimitedUserResolvers; diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index 46cdd0eec0..ffc1a482cc 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -942,6 +942,33 @@ export type FunctionRunStatusInput = { statusMessage?: InputMaybe; }; +export type GendoAiRender = { + __typename?: 'GendoAIRender'; + cameraLocation?: Maybe; + createdAt: Scalars['String']; + gendoGenerationId?: Maybe; + id: Scalars['ID']; + prompt: Scalars['String']; + status: Scalars['String']; + updatedAt: Scalars['String']; +}; + +export type GendoAiRenderCollection = { + __typename?: 'GendoAIRenderCollection'; + items: Array; + totalCount: Scalars['Int']; +}; + +export type GendoAiRenderInput = { + /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ + baseImage: Scalars['String']; + modelId: Scalars['ID']; + projectId: Scalars['ID']; + /** The generation prompt. */ + prompt: Scalars['String']; + versionId: Scalars['ID']; +}; + export type LegacyCommentViewerData = { __typename?: 'LegacyCommentViewerData'; /** @@ -3207,6 +3234,7 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; + gendoAIRenders?: Maybe; id: Scalars['ID']; message?: Maybe; model: Model; @@ -3247,6 +3275,7 @@ export type VersionMutations = { __typename?: 'VersionMutations'; delete: Scalars['Boolean']; moveToModel: Model; + requestGendoAIRender: Scalars['Boolean']; update: Version; }; @@ -3261,6 +3290,11 @@ export type VersionMutationsMoveToModelArgs = { }; +export type VersionMutationsRequestGendoAiRenderArgs = { + input?: InputMaybe; +}; + + export type VersionMutationsUpdateArgs = { input: UpdateVersionInput; }; diff --git a/packages/server/modules/gendo/graph/resolvers/index.ts b/packages/server/modules/gendo/graph/resolvers/index.ts new file mode 100644 index 0000000000..d8fa20094d --- /dev/null +++ b/packages/server/modules/gendo/graph/resolvers/index.ts @@ -0,0 +1,30 @@ +import { authorizeResolver } from '@/modules/shared' +import { Resolvers } from '@/modules/core/graph/generated/graphql' +import { Roles } from '@speckle/shared' + +export = { + Version: { + async gendoAIRenders() { + // TODO + return { + totalCount: 0, + items: [] + } + } + }, + VersionMutations: { + async requestGendoAIRender(__parent, args, ctx) { + console.log(args) + await authorizeResolver( + ctx.userId, + args.input.projectId, + Roles.Stream.Reviewer, + ctx.resourceAccessRules + ) + console.log('hello') + // TODO Fire off request to gendo api & get generationId, create record in db. Note: use gendo api key from env + // TODO Notify this happened + return true + } + } +} as Resolvers diff --git a/packages/server/modules/gendo/helpers/types/index.ts b/packages/server/modules/gendo/helpers/types/index.ts new file mode 100644 index 0000000000..f40d72fe28 --- /dev/null +++ b/packages/server/modules/gendo/helpers/types/index.ts @@ -0,0 +1,13 @@ +export type GendoAIRenderRecord = { + id: string + userId: string + versionId: string + createdAt: string + updatedAt: string + gendoGenerationId: string + status: string + prompt: string + cameraLocation: Record + baseImage: string + responseImage: string +} diff --git a/packages/server/modules/gendo/migrations/20240522130000_gendo.ts b/packages/server/modules/gendo/migrations/20240522130000_gendo.ts new file mode 100644 index 0000000000..a501db4d86 --- /dev/null +++ b/packages/server/modules/gendo/migrations/20240522130000_gendo.ts @@ -0,0 +1,39 @@ +import { Knex } from 'knex' +import { Environment } from '@speckle/shared' + +// TODO: Ask whether migrations should be behind a feature flag or not??? probably... not? as we can get db in inconsistent state +const { FF_GENDOAI_MODULE_ENABLED } = Environment.getFeatureFlags() +const GENDO_TABLE_NAME = 'gendo_ai_renders' + +export async function up(knex: Knex): Promise { + if (!FF_GENDOAI_MODULE_ENABLED) return + // TODO + await knex.schema.createTable(GENDO_TABLE_NAME, (table) => { + table.text('id').primary() + table.text('userId').references('id').inTable('users').onDelete('cascade') + table.text('versionId').references('id').inTable('commits').onDelete('cascade') + + table + .timestamp('createdAt', { precision: 3, useTz: true }) + .defaultTo(knex.fn.now()) + .notNullable() + table + .timestamp('updatedAt', { precision: 3, useTz: true }) + .defaultTo(knex.fn.now()) + .notNullable() + + table.text('gendoGenerationId') // Nullable as the api can fail on first call + table.text('status').notNullable() + table.text('prompt').notNullable() + table.jsonb('cameraLocation').notNullable() + table.text('baseImage').notNullable() // TODO: hopefull these will be blob urls and not the raw deal + table.text('responseImage').notNullable() // TODO: hopefull these will be blob urls and not the raw deal + + table.index(['gendoGenerationId']) + }) +} + +export async function down(knex: Knex): Promise { + if (!FF_GENDOAI_MODULE_ENABLED) return + await knex.schema.dropTable(GENDO_TABLE_NAME) +} diff --git a/packages/server/modules/gendo/services/index.ts b/packages/server/modules/gendo/services/index.ts new file mode 100644 index 0000000000..20a35cbf89 --- /dev/null +++ b/packages/server/modules/gendo/services/index.ts @@ -0,0 +1,29 @@ +import { GendoAIRenders, knex } from '@/modules/core/dbSchema' +import { GendoAiRenderInput } from '@/modules/core/graph/generated/graphql' +import { GendoAIRenderRecord } from '@/modules/gendo/helpers/types' + +export async function createGendoAIRenderRequest( + input: GendoAiRenderInput & { userId: string; status: string } +) { + const [newRecord] = await GendoAIRenders.knex().insert(input, '*') + return newRecord as GendoAIRenderRecord + // TODO Notify +} + +export async function updateGendoAIRenderRequest( + input: Partial<{ status: string; responseImage: string }> & { + gendoGenerationId: string + } +) { + await GendoAIRenders.knex() + .where('gendoGenerationId', input.gendoGenerationId) + .update({ ...input, updatedAt: knex.fn.now() }) + // TODO Notify +} + +export async function getGendoAIRenderRequests(versionId: string) { + return await GendoAIRenders.knex() + .select() + .where('versionId', versionId) + .orderBy('createdAt', 'desc') +} diff --git a/packages/server/modules/shared/helpers/envHelper.ts b/packages/server/modules/shared/helpers/envHelper.ts index 9dffcfef33..522c37a195 100644 --- a/packages/server/modules/shared/helpers/envHelper.ts +++ b/packages/server/modules/shared/helpers/envHelper.ts @@ -289,3 +289,7 @@ export function getAutomateEncryptionKeysPath() { return process.env.AUTOMATE_ENCRYPTION_KEYS_PATH } + +export function getGendoAIKey() { + return process.env.GENDOAI_KEY +} diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 262530ce48..59a4ddcc0d 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -943,6 +943,33 @@ export type FunctionRunStatusInput = { statusMessage?: InputMaybe; }; +export type GendoAiRender = { + __typename?: 'GendoAIRender'; + cameraLocation?: Maybe; + createdAt: Scalars['String']; + gendoGenerationId?: Maybe; + id: Scalars['ID']; + prompt: Scalars['String']; + status: Scalars['String']; + updatedAt: Scalars['String']; +}; + +export type GendoAiRenderCollection = { + __typename?: 'GendoAIRenderCollection'; + items: Array; + totalCount: Scalars['Int']; +}; + +export type GendoAiRenderInput = { + /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ + baseImage: Scalars['String']; + modelId: Scalars['ID']; + projectId: Scalars['ID']; + /** The generation prompt. */ + prompt: Scalars['String']; + versionId: Scalars['ID']; +}; + export type LegacyCommentViewerData = { __typename?: 'LegacyCommentViewerData'; /** @@ -3208,6 +3235,7 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; + gendoAIRenders?: Maybe; id: Scalars['ID']; message?: Maybe; model: Model; @@ -3248,6 +3276,7 @@ export type VersionMutations = { __typename?: 'VersionMutations'; delete: Scalars['Boolean']; moveToModel: Model; + requestGendoAIRender: Scalars['Boolean']; update: Version; }; @@ -3262,6 +3291,11 @@ export type VersionMutationsMoveToModelArgs = { }; +export type VersionMutationsRequestGendoAiRenderArgs = { + input?: InputMaybe; +}; + + export type VersionMutationsUpdateArgs = { input: UpdateVersionInput; }; From 85e92775862c3124b77319fad541cf5540327069 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Thu, 23 May 2024 14:23:08 +0100 Subject: [PATCH 03/27] feat(gendo): wip --- .../components/viewer/gendo/Panel.vue | 27 ++++++++++++++++++- .../modules/gendo/graph/resolvers/index.ts | 9 ++++++- .../modules/shared/helpers/envHelper.ts | 4 +++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/frontend-2/components/viewer/gendo/Panel.vue b/packages/frontend-2/components/viewer/gendo/Panel.vue index 3487221c42..2afa44651f 100644 --- a/packages/frontend-2/components/viewer/gendo/Panel.vue +++ b/packages/frontend-2/components/viewer/gendo/Panel.vue @@ -8,7 +8,7 @@
- Render + Render
@@ -33,7 +33,32 @@ diff --git a/packages/server/modules/gendo/graph/resolvers/index.ts b/packages/server/modules/gendo/graph/resolvers/index.ts index d8fa20094d..ade6829978 100644 --- a/packages/server/modules/gendo/graph/resolvers/index.ts +++ b/packages/server/modules/gendo/graph/resolvers/index.ts @@ -1,6 +1,10 @@ import { authorizeResolver } from '@/modules/shared' import { Resolvers } from '@/modules/core/graph/generated/graphql' import { Roles } from '@speckle/shared' +import { + getGendoAIAPIEndpoint, + getGendoAIKey +} from '@/modules/shared/helpers/envHelper' export = { Version: { @@ -14,13 +18,16 @@ export = { }, VersionMutations: { async requestGendoAIRender(__parent, args, ctx) { - console.log(args) await authorizeResolver( ctx.userId, args.input.projectId, Roles.Stream.Reviewer, ctx.resourceAccessRules ) + + const endpoint = getGendoAIAPIEndpoint() + const bearer = getGendoAIKey() + console.log('hello') // TODO Fire off request to gendo api & get generationId, create record in db. Note: use gendo api key from env // TODO Notify this happened diff --git a/packages/server/modules/shared/helpers/envHelper.ts b/packages/server/modules/shared/helpers/envHelper.ts index 522c37a195..47c18be0a4 100644 --- a/packages/server/modules/shared/helpers/envHelper.ts +++ b/packages/server/modules/shared/helpers/envHelper.ts @@ -293,3 +293,7 @@ export function getAutomateEncryptionKeysPath() { export function getGendoAIKey() { return process.env.GENDOAI_KEY } + +export function getGendoAIAPIEndpoint() { + return process.env.GENDOAI_API_ENDPOINT +} From 0df8fca290c476e2ddf85066e2efd5046f7e753e Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 24 May 2024 10:06:25 +0100 Subject: [PATCH 04/27] feat(gendo): wip --- .../components/viewer/gendo/Panel.vue | 64 +++++++++++++++++-- .../lib/common/generated/gql/gql.ts | 5 ++ .../lib/common/generated/gql/graphql.ts | 11 +++- .../lib/gendo/graphql/queriesAndMutations.ts | 9 +++ .../assets/gendo/typedefs/gendo.graphql | 3 +- .../modules/core/graph/generated/graphql.ts | 5 +- .../graph/generated/graphql.ts | 3 +- .../modules/gendo/graph/resolvers/index.ts | 17 ++++- .../gendo/migrations/20240522130000_gendo.ts | 8 ++- .../server/modules/gendo/services/index.ts | 8 ++- .../server/test/graphql/generated/graphql.ts | 3 +- 11 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts diff --git a/packages/frontend-2/components/viewer/gendo/Panel.vue b/packages/frontend-2/components/viewer/gendo/Panel.vue index 2afa44651f..f8d1c7d8d0 100644 --- a/packages/frontend-2/components/viewer/gendo/Panel.vue +++ b/packages/frontend-2/components/viewer/gendo/Panel.vue @@ -6,7 +6,12 @@
- +
Render
@@ -33,9 +38,17 @@ diff --git a/packages/frontend-2/lib/common/generated/gql/gql.ts b/packages/frontend-2/lib/common/generated/gql/gql.ts index f6ee816f55..a3414d8f1a 100644 --- a/packages/frontend-2/lib/common/generated/gql/gql.ts +++ b/packages/frontend-2/lib/common/generated/gql/gql.ts @@ -124,6 +124,7 @@ const documents = { "\n query DeveloperSettingsAuthorizedApps {\n activeUser {\n id\n authorizedApps {\n id\n description\n name\n author {\n id\n name\n avatar\n }\n }\n }\n }\n": types.DeveloperSettingsAuthorizedAppsDocument, "\n query SearchProjects($search: String, $onlyWithRoles: [String!] = null) {\n activeUser {\n projects(limit: 10, filter: { search: $search, onlyWithRoles: $onlyWithRoles }) {\n totalCount\n items {\n ...FormSelectProjects_Project\n }\n }\n }\n }\n": types.SearchProjectsDocument, "\n query SearchProjectModels($search: String, $projectId: String!) {\n project(id: $projectId) {\n id\n models(limit: 10, filter: { search: $search }) {\n totalCount\n items {\n ...FormSelectModels_Model\n }\n }\n }\n }\n": types.SearchProjectModelsDocument, + "\n mutation requestGendoAIRender($input: GendoAIRenderInput!) {\n versionMutations {\n requestGendoAIRender(input: $input)\n }\n }\n": types.RequestGendoAiRenderDocument, "\n fragment ProjectPageTeamInternals_Project on Project {\n id\n role\n invitedTeam {\n id\n title\n role\n inviteId\n user {\n role\n ...LimitedUserAvatar\n }\n }\n team {\n role\n user {\n role\n ...LimitedUserAvatar\n }\n }\n }\n": types.ProjectPageTeamInternals_ProjectFragmentDoc, "\n fragment ProjectDashboardItemNoModels on Project {\n id\n name\n createdAt\n updatedAt\n role\n team {\n id\n user {\n id\n name\n avatar\n }\n }\n ...ProjectPageModelsCardProject\n }\n": types.ProjectDashboardItemNoModelsFragmentDoc, "\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n models(limit: 4, filter: { onlyWithVersions: true }) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n": types.ProjectDashboardItemFragmentDoc, @@ -688,6 +689,10 @@ export function graphql(source: "\n query SearchProjects($search: String, $only * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "\n query SearchProjectModels($search: String, $projectId: String!) {\n project(id: $projectId) {\n id\n models(limit: 10, filter: { search: $search }) {\n totalCount\n items {\n ...FormSelectModels_Model\n }\n }\n }\n }\n"): (typeof documents)["\n query SearchProjectModels($search: String, $projectId: String!) {\n project(id: $projectId) {\n id\n models(limit: 10, filter: { search: $search }) {\n totalCount\n items {\n ...FormSelectModels_Model\n }\n }\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n mutation requestGendoAIRender($input: GendoAIRenderInput!) {\n versionMutations {\n requestGendoAIRender(input: $input)\n }\n }\n"): (typeof documents)["\n mutation requestGendoAIRender($input: GendoAIRenderInput!) {\n versionMutations {\n requestGendoAIRender(input: $input)\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index b3f78e877a..7757f182ce 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -959,7 +959,6 @@ export type GendoAiRenderCollection = { export type GendoAiRenderInput = { /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ baseImage: Scalars['String']; - modelId: Scalars['ID']; projectId: Scalars['ID']; /** The generation prompt. */ prompt: Scalars['String']; @@ -3288,7 +3287,7 @@ export type VersionMutationsMoveToModelArgs = { export type VersionMutationsRequestGendoAiRenderArgs = { - input?: InputMaybe; + input: GendoAiRenderInput; }; @@ -3800,6 +3799,13 @@ export type SearchProjectModelsQueryVariables = Exact<{ export type SearchProjectModelsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, models: { __typename?: 'ModelCollection', totalCount: number, items: Array<{ __typename?: 'Model', id: string, name: string }> } } }; +export type RequestGendoAiRenderMutationVariables = Exact<{ + input: GendoAiRenderInput; +}>; + + +export type RequestGendoAiRenderMutation = { __typename?: 'Mutation', versionMutations: { __typename?: 'VersionMutations', requestGendoAIRender: boolean } }; + export type ProjectPageTeamInternals_ProjectFragment = { __typename?: 'Project', id: string, role?: string | null, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, role: string, inviteId: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }> }; export type ProjectDashboardItemNoModelsFragment = { __typename?: 'Project', id: string, name: string, createdAt: string, updatedAt: string, role?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, team: Array<{ __typename?: 'ProjectCollaborator', id: string, user: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } }> }; @@ -4602,6 +4608,7 @@ export const DeveloperSettingsApplicationsDocument = {"kind":"Document","definit export const DeveloperSettingsAuthorizedAppsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"DeveloperSettingsAuthorizedApps"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"authorizedApps"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"author"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"avatar"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const SearchProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SearchProjects"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"search"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"onlyWithRoles"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},"defaultValue":{"kind":"NullValue"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"search"},"value":{"kind":"Variable","name":{"kind":"Name","value":"search"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"onlyWithRoles"},"value":{"kind":"Variable","name":{"kind":"Name","value":"onlyWithRoles"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormSelectProjects_Project"}}]}}]}}]}}]}},...FormSelectProjects_ProjectFragmentDoc.definitions]} as unknown as DocumentNode; export const SearchProjectModelsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SearchProjectModels"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"search"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"search"},"value":{"kind":"Variable","name":{"kind":"Name","value":"search"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormSelectModels_Model"}}]}}]}}]}}]}},...FormSelectModels_ModelFragmentDoc.definitions]} as unknown as DocumentNode; +export const RequestGendoAiRenderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"requestGendoAIRender"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"GendoAIRenderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"requestGendoAIRender"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]}}]} as unknown as DocumentNode; export const CreateModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...AutomateRunsTriggerStatus_TriggeredAutomationsStatusFragmentDoc.definitions,...TriggeredAutomationsStatusSummaryFragmentDoc.definitions,...FunctionRunStatusForSummaryFragmentDoc.definitions,...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatusFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogRunsRows_AutomateRunFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRunFragmentDoc.definitions,...AutomationsStatusOrderedRuns_AutomationRunFragmentDoc.definitions]} as unknown as DocumentNode; export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectCreateInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...AutomateRunsTriggerStatus_TriggeredAutomationsStatusFragmentDoc.definitions,...TriggeredAutomationsStatusSummaryFragmentDoc.definitions,...FunctionRunStatusForSummaryFragmentDoc.definitions,...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatusFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogRunsRows_AutomateRunFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRunFragmentDoc.definitions,...AutomationsStatusOrderedRuns_AutomationRunFragmentDoc.definitions]} as unknown as DocumentNode; export const UpdateModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...AutomateRunsTriggerStatus_TriggeredAutomationsStatusFragmentDoc.definitions,...TriggeredAutomationsStatusSummaryFragmentDoc.definitions,...FunctionRunStatusForSummaryFragmentDoc.definitions,...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatusFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogRunsRows_AutomateRunFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRunFragmentDoc.definitions,...AutomationsStatusOrderedRuns_AutomationRunFragmentDoc.definitions]} as unknown as DocumentNode; diff --git a/packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts b/packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts new file mode 100644 index 0000000000..d2089f3d3e --- /dev/null +++ b/packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts @@ -0,0 +1,9 @@ +import { graphql } from '~~/lib/common/generated/gql' + +export const requestGendoAIRender = graphql(` + mutation requestGendoAIRender($input: GendoAIRenderInput!) { + versionMutations { + requestGendoAIRender(input: $input) + } + } +`) diff --git a/packages/server/assets/gendo/typedefs/gendo.graphql b/packages/server/assets/gendo/typedefs/gendo.graphql index 9dd5b7e461..f52a605614 100644 --- a/packages/server/assets/gendo/typedefs/gendo.graphql +++ b/packages/server/assets/gendo/typedefs/gendo.graphql @@ -18,13 +18,14 @@ type GendoAIRender { } extend type VersionMutations { - requestGendoAIRender(input: GendoAIRenderInput): Boolean! + requestGendoAIRender(input: GendoAIRenderInput!): Boolean! } input GendoAIRenderInput { projectId: ID! modelId: ID! versionId: ID! + camera: JSONObject! """ The generation prompt. """ diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index 6a49454553..0d7369172b 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -973,6 +973,7 @@ export type GendoAiRenderCollection = { export type GendoAiRenderInput = { /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ baseImage: Scalars['String']; + camera: Scalars['JSONObject']; modelId: Scalars['ID']; projectId: Scalars['ID']; /** The generation prompt. */ @@ -3302,7 +3303,7 @@ export type VersionMutationsMoveToModelArgs = { export type VersionMutationsRequestGendoAiRenderArgs = { - input?: InputMaybe; + input: GendoAiRenderInput; }; @@ -5108,7 +5109,7 @@ export type VersionCreatedTriggerDefinitionResolvers = { delete?: Resolver>; moveToModel?: Resolver>; - requestGendoAIRender?: Resolver>; + requestGendoAIRender?: Resolver>; update?: Resolver>; __isTypeOf?: IsTypeOfResolverFn; }; diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index ffc1a482cc..b59270f906 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -962,6 +962,7 @@ export type GendoAiRenderCollection = { export type GendoAiRenderInput = { /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ baseImage: Scalars['String']; + camera: Scalars['JSONObject']; modelId: Scalars['ID']; projectId: Scalars['ID']; /** The generation prompt. */ @@ -3291,7 +3292,7 @@ export type VersionMutationsMoveToModelArgs = { export type VersionMutationsRequestGendoAiRenderArgs = { - input?: InputMaybe; + input: GendoAiRenderInput; }; diff --git a/packages/server/modules/gendo/graph/resolvers/index.ts b/packages/server/modules/gendo/graph/resolvers/index.ts index ade6829978..56c7b5f289 100644 --- a/packages/server/modules/gendo/graph/resolvers/index.ts +++ b/packages/server/modules/gendo/graph/resolvers/index.ts @@ -5,6 +5,8 @@ import { getGendoAIAPIEndpoint, getGendoAIKey } from '@/modules/shared/helpers/envHelper' +import { createGendoAIRenderRequest } from '@/modules/gendo/services' +import crs from 'crypto-random-string' export = { Version: { @@ -28,8 +30,21 @@ export = { const endpoint = getGendoAIAPIEndpoint() const bearer = getGendoAIKey() - console.log('hello') + const log = { ...args.input, endpoint, bearer } + delete log.baseImage + console.log(log) + // TODO Fire off request to gendo api & get generationId, create record in db. Note: use gendo api key from env + + const res = await createGendoAIRenderRequest({ + ...args.input, + userId: ctx.userId as string, + status: 'TEST', + gendoGenerationId: '42', + id: crs({ length: 10 }) + }) + + console.log(res, 'gendo') // TODO Notify this happened return true } diff --git a/packages/server/modules/gendo/migrations/20240522130000_gendo.ts b/packages/server/modules/gendo/migrations/20240522130000_gendo.ts index a501db4d86..fa58713ee7 100644 --- a/packages/server/modules/gendo/migrations/20240522130000_gendo.ts +++ b/packages/server/modules/gendo/migrations/20240522130000_gendo.ts @@ -11,6 +11,8 @@ export async function up(knex: Knex): Promise { await knex.schema.createTable(GENDO_TABLE_NAME, (table) => { table.text('id').primary() table.text('userId').references('id').inTable('users').onDelete('cascade') + table.text('projectId').references('id').inTable('streams').onDelete('cascade') + table.text('modelId').references('id').inTable('branches').onDelete('cascade') table.text('versionId').references('id').inTable('commits').onDelete('cascade') table @@ -22,12 +24,12 @@ export async function up(knex: Knex): Promise { .defaultTo(knex.fn.now()) .notNullable() - table.text('gendoGenerationId') // Nullable as the api can fail on first call + table.text('gendoGenerationId') // Nullable as the api can fail on first call (?) table.text('status').notNullable() table.text('prompt').notNullable() - table.jsonb('cameraLocation').notNullable() + table.jsonb('camera').notNullable() table.text('baseImage').notNullable() // TODO: hopefull these will be blob urls and not the raw deal - table.text('responseImage').notNullable() // TODO: hopefull these will be blob urls and not the raw deal + table.text('responseImage') table.index(['gendoGenerationId']) }) diff --git a/packages/server/modules/gendo/services/index.ts b/packages/server/modules/gendo/services/index.ts index 20a35cbf89..08ec912e88 100644 --- a/packages/server/modules/gendo/services/index.ts +++ b/packages/server/modules/gendo/services/index.ts @@ -1,9 +1,15 @@ import { GendoAIRenders, knex } from '@/modules/core/dbSchema' import { GendoAiRenderInput } from '@/modules/core/graph/generated/graphql' import { GendoAIRenderRecord } from '@/modules/gendo/helpers/types' +import cryptoRandomString from 'crypto-random-string' export async function createGendoAIRenderRequest( - input: GendoAiRenderInput & { userId: string; status: string } + input: GendoAiRenderInput & { + userId: string + status: string + id: string + gendoGenerationId?: string + } ) { const [newRecord] = await GendoAIRenders.knex().insert(input, '*') return newRecord as GendoAIRenderRecord diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 59a4ddcc0d..33e7344245 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -963,6 +963,7 @@ export type GendoAiRenderCollection = { export type GendoAiRenderInput = { /** Base64 encoded image of the depthmap, resized to 1024 on the longest size. */ baseImage: Scalars['String']; + camera: Scalars['JSONObject']; modelId: Scalars['ID']; projectId: Scalars['ID']; /** The generation prompt. */ @@ -3292,7 +3293,7 @@ export type VersionMutationsMoveToModelArgs = { export type VersionMutationsRequestGendoAiRenderArgs = { - input?: InputMaybe; + input: GendoAiRenderInput; }; From f47d2b83ac1067da48dc26fd50c5dedce2fa56ce Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 24 May 2024 17:11:55 +0100 Subject: [PATCH 05/27] feat(gendo): wip --- .../components/viewer/gendo/Panel.vue | 19 +++++--- .../lib/common/generated/gql/graphql.ts | 2 + .../modules/gendo/graph/resolvers/index.ts | 47 ++++++++++++++----- packages/server/modules/gendo/index.ts | 31 ++++++++++-- .../server/modules/gendo/services/index.ts | 1 - .../modules/shared/helpers/envHelper.ts | 4 ++ 6 files changed, 78 insertions(+), 26 deletions(-) diff --git a/packages/frontend-2/components/viewer/gendo/Panel.vue b/packages/frontend-2/components/viewer/gendo/Panel.vue index f8d1c7d8d0..875f39c3b4 100644 --- a/packages/frontend-2/components/viewer/gendo/Panel.vue +++ b/packages/frontend-2/components/viewer/gendo/Panel.vue @@ -5,7 +5,7 @@ (Beta)
-
+
- Render + Render
@@ -28,7 +28,7 @@ link size="sm" class="ml-1" - to="https://gendo.ai" + to="https://gendo.ai?utm=speckle" target="_blank" > Gendo @@ -38,7 +38,7 @@ diff --git a/packages/frontend-2/components/viewer/gendo/Panel.vue b/packages/frontend-2/components/viewer/gendo/Panel.vue index 875f39c3b4..c3404b5a29 100644 --- a/packages/frontend-2/components/viewer/gendo/Panel.vue +++ b/packages/frontend-2/components/viewer/gendo/Panel.vue @@ -13,11 +13,14 @@ placeholder="Your prompt" />
- Render + + Render +
+
- TODO Empty state explaining WTF this does + TODO Empty state explaining this does
-
+
-
+
+ Hide history Render
- +
TODO Empty state explaining this does
@@ -61,6 +62,7 @@ defineEmits<{ const prompt = ref() const isLoading = ref(false) +const showHistory = ref(true) const enqueMagic = () => { isLoading.value = true diff --git a/packages/frontend-2/lib/common/generated/gql/gql.ts b/packages/frontend-2/lib/common/generated/gql/gql.ts index a3414d8f1a..4f68cceeb9 100644 --- a/packages/frontend-2/lib/common/generated/gql/gql.ts +++ b/packages/frontend-2/lib/common/generated/gql/gql.ts @@ -125,6 +125,10 @@ const documents = { "\n query SearchProjects($search: String, $onlyWithRoles: [String!] = null) {\n activeUser {\n projects(limit: 10, filter: { search: $search, onlyWithRoles: $onlyWithRoles }) {\n totalCount\n items {\n ...FormSelectProjects_Project\n }\n }\n }\n }\n": types.SearchProjectsDocument, "\n query SearchProjectModels($search: String, $projectId: String!) {\n project(id: $projectId) {\n id\n models(limit: 10, filter: { search: $search }) {\n totalCount\n items {\n ...FormSelectModels_Model\n }\n }\n }\n }\n": types.SearchProjectModelsDocument, "\n mutation requestGendoAIRender($input: GendoAIRenderInput!) {\n versionMutations {\n requestGendoAIRender(input: $input)\n }\n }\n": types.RequestGendoAiRenderDocument, + "\n query GendoAIRender(\n $gendoAiRenderId: String!\n $versionId: String!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n version(id: $versionId) {\n id\n gendoAIRender(id: $gendoAiRenderId) {\n id\n projectId\n modelId\n versionId\n createdAt\n updatedAt\n gendoGenerationId\n status\n prompt\n camera\n responseImage\n }\n }\n }\n }\n": types.GendoAiRenderDocument, + "\n query GendoAIRenders($versionId: String!, $projectId: String!) {\n project(id: $projectId) {\n id\n version(id: $versionId) {\n id\n gendoAIRenders {\n totalCount\n items {\n id\n createdAt\n updatedAt\n status\n gendoGenerationId\n prompt\n camera\n }\n }\n }\n }\n }\n": types.GendoAiRendersDocument, + "\n subscription ProjectVersionGendoAIRenderCreated($id: String!, $versionId: String!) {\n projectVersionGendoAIRenderCreated(id: $id, versionId: $versionId) {\n id\n createdAt\n updatedAt\n status\n gendoGenerationId\n prompt\n camera\n }\n }\n": types.ProjectVersionGendoAiRenderCreatedDocument, + "\n subscription ProjectVersionGendoAIRenderUpdated($id: String!, $versionId: String!) {\n projectVersionGendoAIRenderUpdated(id: $id, versionId: $versionId) {\n id\n projectId\n modelId\n versionId\n createdAt\n updatedAt\n gendoGenerationId\n status\n prompt\n camera\n responseImage\n }\n }\n": types.ProjectVersionGendoAiRenderUpdatedDocument, "\n fragment ProjectPageTeamInternals_Project on Project {\n id\n role\n invitedTeam {\n id\n title\n role\n inviteId\n user {\n role\n ...LimitedUserAvatar\n }\n }\n team {\n role\n user {\n role\n ...LimitedUserAvatar\n }\n }\n }\n": types.ProjectPageTeamInternals_ProjectFragmentDoc, "\n fragment ProjectDashboardItemNoModels on Project {\n id\n name\n createdAt\n updatedAt\n role\n team {\n id\n user {\n id\n name\n avatar\n }\n }\n ...ProjectPageModelsCardProject\n }\n": types.ProjectDashboardItemNoModelsFragmentDoc, "\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n models(limit: 4, filter: { onlyWithVersions: true }) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n": types.ProjectDashboardItemFragmentDoc, @@ -693,6 +697,22 @@ export function graphql(source: "\n query SearchProjectModels($search: String, * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql(source: "\n mutation requestGendoAIRender($input: GendoAIRenderInput!) {\n versionMutations {\n requestGendoAIRender(input: $input)\n }\n }\n"): (typeof documents)["\n mutation requestGendoAIRender($input: GendoAIRenderInput!) {\n versionMutations {\n requestGendoAIRender(input: $input)\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n query GendoAIRender(\n $gendoAiRenderId: String!\n $versionId: String!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n version(id: $versionId) {\n id\n gendoAIRender(id: $gendoAiRenderId) {\n id\n projectId\n modelId\n versionId\n createdAt\n updatedAt\n gendoGenerationId\n status\n prompt\n camera\n responseImage\n }\n }\n }\n }\n"): (typeof documents)["\n query GendoAIRender(\n $gendoAiRenderId: String!\n $versionId: String!\n $projectId: String!\n ) {\n project(id: $projectId) {\n id\n version(id: $versionId) {\n id\n gendoAIRender(id: $gendoAiRenderId) {\n id\n projectId\n modelId\n versionId\n createdAt\n updatedAt\n gendoGenerationId\n status\n prompt\n camera\n responseImage\n }\n }\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n query GendoAIRenders($versionId: String!, $projectId: String!) {\n project(id: $projectId) {\n id\n version(id: $versionId) {\n id\n gendoAIRenders {\n totalCount\n items {\n id\n createdAt\n updatedAt\n status\n gendoGenerationId\n prompt\n camera\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query GendoAIRenders($versionId: String!, $projectId: String!) {\n project(id: $projectId) {\n id\n version(id: $versionId) {\n id\n gendoAIRenders {\n totalCount\n items {\n id\n createdAt\n updatedAt\n status\n gendoGenerationId\n prompt\n camera\n }\n }\n }\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n subscription ProjectVersionGendoAIRenderCreated($id: String!, $versionId: String!) {\n projectVersionGendoAIRenderCreated(id: $id, versionId: $versionId) {\n id\n createdAt\n updatedAt\n status\n gendoGenerationId\n prompt\n camera\n }\n }\n"): (typeof documents)["\n subscription ProjectVersionGendoAIRenderCreated($id: String!, $versionId: String!) {\n projectVersionGendoAIRenderCreated(id: $id, versionId: $versionId) {\n id\n createdAt\n updatedAt\n status\n gendoGenerationId\n prompt\n camera\n }\n }\n"]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n subscription ProjectVersionGendoAIRenderUpdated($id: String!, $versionId: String!) {\n projectVersionGendoAIRenderUpdated(id: $id, versionId: $versionId) {\n id\n projectId\n modelId\n versionId\n createdAt\n updatedAt\n gendoGenerationId\n status\n prompt\n camera\n responseImage\n }\n }\n"): (typeof documents)["\n subscription ProjectVersionGendoAIRenderUpdated($id: String!, $versionId: String!) {\n projectVersionGendoAIRenderUpdated(id: $id, versionId: $versionId) {\n id\n projectId\n modelId\n versionId\n createdAt\n updatedAt\n gendoGenerationId\n status\n prompt\n camera\n responseImage\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/packages/frontend-2/lib/common/generated/gql/graphql.ts b/packages/frontend-2/lib/common/generated/gql/graphql.ts index a186538320..8acf68fabe 100644 --- a/packages/frontend-2/lib/common/generated/gql/graphql.ts +++ b/packages/frontend-2/lib/common/generated/gql/graphql.ts @@ -941,14 +941,14 @@ export type FunctionRunStatusInput = { export type GendoAiRender = { __typename?: 'GendoAIRender'; - cameraLocation?: Maybe; + camera?: Maybe; createdAt: Scalars['String']; gendoGenerationId?: Maybe; id: Scalars['ID']; modelId: Scalars['String']; projectId: Scalars['String']; prompt: Scalars['String']; - responseImage: Scalars['String']; + responseImage?: Maybe; status: Scalars['String']; updatedAt: Scalars['String']; versionId: Scalars['String']; @@ -3250,7 +3250,8 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; - gendoAIRenders?: Maybe; + gendoAIRender: GendoAiRender; + gendoAIRenders: GendoAiRenderCollection; id: Scalars['ID']; message?: Maybe; model: Model; @@ -3267,6 +3268,11 @@ export type VersionCommentThreadsArgs = { limit?: Scalars['Int']; }; + +export type VersionGendoAiRenderArgs = { + id: Scalars['String']; +}; + export type VersionCollection = { __typename?: 'VersionCollection'; cursor?: Maybe; @@ -3826,6 +3832,39 @@ export type RequestGendoAiRenderMutationVariables = Exact<{ export type RequestGendoAiRenderMutation = { __typename?: 'Mutation', versionMutations: { __typename?: 'VersionMutations', requestGendoAIRender: boolean } }; +export type GendoAiRenderQueryVariables = Exact<{ + gendoAiRenderId: Scalars['String']; + versionId: Scalars['String']; + projectId: Scalars['String']; +}>; + + +export type GendoAiRenderQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, version?: { __typename?: 'Version', id: string, gendoAIRender: { __typename?: 'GendoAIRender', id: string, projectId: string, modelId: string, versionId: string, createdAt: string, updatedAt: string, gendoGenerationId?: string | null, status: string, prompt: string, camera?: {} | null, responseImage?: string | null } } | null } }; + +export type GendoAiRendersQueryVariables = Exact<{ + versionId: Scalars['String']; + projectId: Scalars['String']; +}>; + + +export type GendoAiRendersQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, version?: { __typename?: 'Version', id: string, gendoAIRenders: { __typename?: 'GendoAIRenderCollection', totalCount: number, items: Array<{ __typename?: 'GendoAIRender', id: string, createdAt: string, updatedAt: string, status: string, gendoGenerationId?: string | null, prompt: string, camera?: {} | null } | null> } } | null } }; + +export type ProjectVersionGendoAiRenderCreatedSubscriptionVariables = Exact<{ + id: Scalars['String']; + versionId: Scalars['String']; +}>; + + +export type ProjectVersionGendoAiRenderCreatedSubscription = { __typename?: 'Subscription', projectVersionGendoAIRenderCreated: { __typename?: 'GendoAIRender', id: string, createdAt: string, updatedAt: string, status: string, gendoGenerationId?: string | null, prompt: string, camera?: {} | null } }; + +export type ProjectVersionGendoAiRenderUpdatedSubscriptionVariables = Exact<{ + id: Scalars['String']; + versionId: Scalars['String']; +}>; + + +export type ProjectVersionGendoAiRenderUpdatedSubscription = { __typename?: 'Subscription', projectVersionGendoAIRenderUpdated: { __typename?: 'GendoAIRender', id: string, projectId: string, modelId: string, versionId: string, createdAt: string, updatedAt: string, gendoGenerationId?: string | null, status: string, prompt: string, camera?: {} | null, responseImage?: string | null } }; + export type ProjectPageTeamInternals_ProjectFragment = { __typename?: 'Project', id: string, role?: string | null, invitedTeam?: Array<{ __typename?: 'PendingStreamCollaborator', id: string, title: string, role: string, inviteId: string, user?: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } | null }> | null, team: Array<{ __typename?: 'ProjectCollaborator', role: string, user: { __typename?: 'LimitedUser', role?: string | null, id: string, name: string, avatar?: string | null } }> }; export type ProjectDashboardItemNoModelsFragment = { __typename?: 'Project', id: string, name: string, createdAt: string, updatedAt: string, role?: string | null, visibility: ProjectVisibility, allowPublicComments: boolean, team: Array<{ __typename?: 'ProjectCollaborator', id: string, user: { __typename?: 'LimitedUser', id: string, name: string, avatar?: string | null } }> }; @@ -4629,6 +4668,10 @@ export const DeveloperSettingsAuthorizedAppsDocument = {"kind":"Document","defin export const SearchProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SearchProjects"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"search"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"onlyWithRoles"}},"type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},"defaultValue":{"kind":"NullValue"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"search"},"value":{"kind":"Variable","name":{"kind":"Name","value":"search"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"onlyWithRoles"},"value":{"kind":"Variable","name":{"kind":"Name","value":"onlyWithRoles"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormSelectProjects_Project"}}]}}]}}]}}]}},...FormSelectProjects_ProjectFragmentDoc.definitions]} as unknown as DocumentNode; export const SearchProjectModelsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SearchProjectModels"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"search"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"10"}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"search"},"value":{"kind":"Variable","name":{"kind":"Name","value":"search"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"FormSelectModels_Model"}}]}}]}}]}}]}},...FormSelectModels_ModelFragmentDoc.definitions]} as unknown as DocumentNode; export const RequestGendoAiRenderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"requestGendoAIRender"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"GendoAIRenderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"requestGendoAIRender"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]}}]} as unknown as DocumentNode; +export const GendoAiRenderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GendoAIRender"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"gendoAiRenderId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"version"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"gendoAIRender"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"gendoAiRenderId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"versionId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"gendoGenerationId"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"prompt"}},{"kind":"Field","name":{"kind":"Name","value":"camera"}},{"kind":"Field","name":{"kind":"Name","value":"responseImage"}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const GendoAiRendersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GendoAIRenders"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"version"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"gendoAIRenders"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"gendoGenerationId"}},{"kind":"Field","name":{"kind":"Name","value":"prompt"}},{"kind":"Field","name":{"kind":"Name","value":"camera"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const ProjectVersionGendoAiRenderCreatedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"ProjectVersionGendoAIRenderCreated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectVersionGendoAIRenderCreated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"versionId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"gendoGenerationId"}},{"kind":"Field","name":{"kind":"Name","value":"prompt"}},{"kind":"Field","name":{"kind":"Name","value":"camera"}}]}}]}}]} as unknown as DocumentNode; +export const ProjectVersionGendoAiRenderUpdatedDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"subscription","name":{"kind":"Name","value":"ProjectVersionGendoAIRenderUpdated"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectVersionGendoAIRenderUpdated"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"kind":"Argument","name":{"kind":"Name","value":"versionId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"versionId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projectId"}},{"kind":"Field","name":{"kind":"Name","value":"modelId"}},{"kind":"Field","name":{"kind":"Name","value":"versionId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"gendoGenerationId"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"prompt"}},{"kind":"Field","name":{"kind":"Name","value":"camera"}},{"kind":"Field","name":{"kind":"Name","value":"responseImage"}}]}}]}}]} as unknown as DocumentNode; export const CreateModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...AutomateRunsTriggerStatus_TriggeredAutomationsStatusFragmentDoc.definitions,...TriggeredAutomationsStatusSummaryFragmentDoc.definitions,...FunctionRunStatusForSummaryFragmentDoc.definitions,...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatusFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogRunsRows_AutomateRunFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRunFragmentDoc.definitions,...AutomationsStatusOrderedRuns_AutomationRunFragmentDoc.definitions]} as unknown as DocumentNode; export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectCreateInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageProject"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectDashboardItem"}}]}}]}}]}},...ProjectPageProjectFragmentDoc.definitions,...ProjectPageProjectHeaderFragmentDoc.definitions,...ProjectPageTeamDialogFragmentDoc.definitions,...LimitedUserAvatarFragmentDoc.definitions,...ProjectsPageTeamDialogManagePermissions_ProjectFragmentDoc.definitions,...ProjectDashboardItemFragmentDoc.definitions,...ProjectDashboardItemNoModelsFragmentDoc.definitions,...ProjectPageModelsCardProjectFragmentDoc.definitions,...ProjectPageModelsActions_ProjectFragmentDoc.definitions,...ProjectsModelPageEmbed_ProjectFragmentDoc.definitions,...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...AutomateRunsTriggerStatus_TriggeredAutomationsStatusFragmentDoc.definitions,...TriggeredAutomationsStatusSummaryFragmentDoc.definitions,...FunctionRunStatusForSummaryFragmentDoc.definitions,...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatusFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogRunsRows_AutomateRunFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRunFragmentDoc.definitions,...AutomationsStatusOrderedRuns_AutomationRunFragmentDoc.definitions]} as unknown as DocumentNode; export const UpdateModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectPageLatestItemsModelItem"}}]}}]}}]}},...ProjectPageLatestItemsModelItemFragmentDoc.definitions,...PendingFileUploadFragmentDoc.definitions,...ProjectPageModelsCardRenameDialogFragmentDoc.definitions,...ProjectPageModelsCardDeleteDialogFragmentDoc.definitions,...ProjectPageModelsActionsFragmentDoc.definitions,...AutomateRunsTriggerStatus_TriggeredAutomationsStatusFragmentDoc.definitions,...TriggeredAutomationsStatusSummaryFragmentDoc.definitions,...FunctionRunStatusForSummaryFragmentDoc.definitions,...AutomateRunsTriggerStatusDialog_TriggeredAutomationsStatusFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogRunsRows_AutomateRunFragmentDoc.definitions,...AutomateRunsTriggerStatusDialogFunctionRun_AutomateFunctionRunFragmentDoc.definitions,...AutomationsStatusOrderedRuns_AutomationRunFragmentDoc.definitions]} as unknown as DocumentNode; diff --git a/packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts b/packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts index d2089f3d3e..c275829824 100644 --- a/packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts +++ b/packages/frontend-2/lib/gendo/graphql/queriesAndMutations.ts @@ -7,3 +7,92 @@ export const requestGendoAIRender = graphql(` } } `) + +/** + * Get an individual gendo ai render + */ +export const getGendoAIRender = graphql(` + query GendoAIRender( + $gendoAiRenderId: String! + $versionId: String! + $projectId: String! + ) { + project(id: $projectId) { + id + version(id: $versionId) { + id + gendoAIRender(id: $gendoAiRenderId) { + id + projectId + modelId + versionId + createdAt + updatedAt + gendoGenerationId + status + prompt + camera + responseImage + } + } + } + } +`) + +/** + * Get the version's list of gendo ai renders + */ +export const getGendoAIRenders = graphql(` + query GendoAIRenders($versionId: String!, $projectId: String!) { + project(id: $projectId) { + id + version(id: $versionId) { + id + gendoAIRenders { + totalCount + items { + id + createdAt + updatedAt + status + gendoGenerationId + prompt + camera + } + } + } + } + } +`) + +export const onGendoAiRenderCreated = graphql(` + subscription ProjectVersionGendoAIRenderCreated($id: String!, $versionId: String!) { + projectVersionGendoAIRenderCreated(id: $id, versionId: $versionId) { + id + createdAt + updatedAt + status + gendoGenerationId + prompt + camera + } + } +`) + +export const onGendoAiRenderUpdated = graphql(` + subscription ProjectVersionGendoAIRenderUpdated($id: String!, $versionId: String!) { + projectVersionGendoAIRenderUpdated(id: $id, versionId: $versionId) { + id + projectId + modelId + versionId + createdAt + updatedAt + gendoGenerationId + status + prompt + camera + responseImage + } + } +`) diff --git a/packages/server/assets/gendo/typedefs/gendo.graphql b/packages/server/assets/gendo/typedefs/gendo.graphql index d4301485cc..cf6cfc08c0 100644 --- a/packages/server/assets/gendo/typedefs/gendo.graphql +++ b/packages/server/assets/gendo/typedefs/gendo.graphql @@ -1,6 +1,6 @@ extend type Version { - gendoAIRenders: GendoAIRenderCollection - gendoAIRender(id: String!): GendoAIRender + gendoAIRenders: GendoAIRenderCollection! + gendoAIRender(id: String!): GendoAIRender! } type GendoAIRenderCollection { @@ -18,8 +18,8 @@ type GendoAIRender { gendoGenerationId: String status: String! prompt: String! - cameraLocation: JSONObject - responseImage: String! + camera: JSONObject + responseImage: String } extend type VersionMutations { diff --git a/packages/server/modules/core/graph/generated/graphql.ts b/packages/server/modules/core/graph/generated/graphql.ts index 4bfae2fcd9..de9d311ddd 100644 --- a/packages/server/modules/core/graph/generated/graphql.ts +++ b/packages/server/modules/core/graph/generated/graphql.ts @@ -955,14 +955,14 @@ export type FunctionRunStatusInput = { export type GendoAiRender = { __typename?: 'GendoAIRender'; - cameraLocation?: Maybe; + camera?: Maybe; createdAt: Scalars['String']; gendoGenerationId?: Maybe; id: Scalars['ID']; modelId: Scalars['String']; projectId: Scalars['String']; prompt: Scalars['String']; - responseImage: Scalars['String']; + responseImage?: Maybe; status: Scalars['String']; updatedAt: Scalars['String']; versionId: Scalars['String']; @@ -3264,8 +3264,8 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; - gendoAIRender?: Maybe; - gendoAIRenders?: Maybe; + gendoAIRender: GendoAiRender; + gendoAIRenders: GendoAiRenderCollection; id: Scalars['ID']; message?: Maybe; model: Model; @@ -4421,14 +4421,14 @@ export type FileUploadResolvers = { - cameraLocation?: Resolver, ParentType, ContextType>; + camera?: Resolver, ParentType, ContextType>; createdAt?: Resolver; gendoGenerationId?: Resolver, ParentType, ContextType>; id?: Resolver; modelId?: Resolver; projectId?: Resolver; prompt?: Resolver; - responseImage?: Resolver; + responseImage?: Resolver, ParentType, ContextType>; status?: Resolver; updatedAt?: Resolver; versionId?: Resolver; @@ -5104,8 +5104,8 @@ export type VersionResolvers, ParentType, ContextType>; commentThreads?: Resolver>; createdAt?: Resolver; - gendoAIRender?: Resolver, ParentType, ContextType, RequireFields>; - gendoAIRenders?: Resolver, ParentType, ContextType>; + gendoAIRender?: Resolver>; + gendoAIRenders?: Resolver; id?: Resolver; message?: Resolver, ParentType, ContextType>; model?: Resolver; diff --git a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts index c561d17888..8dedff127d 100644 --- a/packages/server/modules/cross-server-sync/graph/generated/graphql.ts +++ b/packages/server/modules/cross-server-sync/graph/generated/graphql.ts @@ -944,14 +944,14 @@ export type FunctionRunStatusInput = { export type GendoAiRender = { __typename?: 'GendoAIRender'; - cameraLocation?: Maybe; + camera?: Maybe; createdAt: Scalars['String']; gendoGenerationId?: Maybe; id: Scalars['ID']; modelId: Scalars['String']; projectId: Scalars['String']; prompt: Scalars['String']; - responseImage: Scalars['String']; + responseImage?: Maybe; status: Scalars['String']; updatedAt: Scalars['String']; versionId: Scalars['String']; @@ -3253,8 +3253,8 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; - gendoAIRender?: Maybe; - gendoAIRenders?: Maybe; + gendoAIRender: GendoAiRender; + gendoAIRenders: GendoAiRenderCollection; id: Scalars['ID']; message?: Maybe; model: Model; diff --git a/packages/server/test/graphql/generated/graphql.ts b/packages/server/test/graphql/generated/graphql.ts index 3d401a9158..964949c6c3 100644 --- a/packages/server/test/graphql/generated/graphql.ts +++ b/packages/server/test/graphql/generated/graphql.ts @@ -945,14 +945,14 @@ export type FunctionRunStatusInput = { export type GendoAiRender = { __typename?: 'GendoAIRender'; - cameraLocation?: Maybe; + camera?: Maybe; createdAt: Scalars['String']; gendoGenerationId?: Maybe; id: Scalars['ID']; modelId: Scalars['String']; projectId: Scalars['String']; prompt: Scalars['String']; - responseImage: Scalars['String']; + responseImage?: Maybe; status: Scalars['String']; updatedAt: Scalars['String']; versionId: Scalars['String']; @@ -3254,8 +3254,8 @@ export type Version = { /** All comment threads in this version */ commentThreads: CommentCollection; createdAt: Scalars['DateTime']; - gendoAIRender?: Maybe; - gendoAIRenders?: Maybe; + gendoAIRender: GendoAiRender; + gendoAIRenders: GendoAiRenderCollection; id: Scalars['ID']; message?: Maybe; model: Model; From ce888fd261322ee49ab8dc702c9b7ea04297cf97 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Sun, 26 May 2024 11:45:03 +0100 Subject: [PATCH 08/27] feat(gendo): wip --- .../frontend-2/components/viewer/Controls.vue | 68 +++++++++++++++++-- .../components/viewer/gendo/Item.vue | 11 +-- .../components/viewer/gendo/List.vue | 9 +-- .../components/viewer/gendo/Panel.vue | 38 ++++++++--- .../lib/common/generated/gql/gql.ts | 4 +- .../lib/common/generated/gql/graphql.ts | 13 +++- .../lib/gendo/graphql/queriesAndMutations.ts | 5 ++ .../server/assets/core/typedefs/user.graphql | 6 ++ .../assets/gendo/typedefs/gendo.graphql | 2 + packages/server/modules/core/dbSchema.ts | 4 +- .../modules/core/graph/generated/graphql.ts | 21 ++++++ .../modules/core/services/ratelimiter.ts | 10 +++ .../graph/generated/graphql.ts | 9 +++ .../modules/gendo/graph/resolvers/index.ts | 7 +- .../modules/gendo/helpers/types/index.ts | 2 +- .../server/modules/gendo/services/index.ts | 28 +++++--- .../server/test/graphql/generated/graphql.ts | 9 +++ 17 files changed, 202 insertions(+), 44 deletions(-) diff --git a/packages/frontend-2/components/viewer/Controls.vue b/packages/frontend-2/components/viewer/Controls.vue index f6dfe9ba2d..fbae7e7f31 100644 --- a/packages/frontend-2/components/viewer/Controls.vue +++ b/packages/frontend-2/components/viewer/Controls.vue @@ -156,13 +156,32 @@
+
@@ -232,7 +251,8 @@ import { ArrowsPointingOutIcon, ScissorsIcon, PlusIcon, - ChevronDoubleRightIcon + ChevronDoubleRightIcon, + ArrowsRightLeftIcon } from '@heroicons/vue/24/outline' import { isNonNullable, type Nullable } from '@speckle/shared' import { @@ -254,12 +274,53 @@ import { useMixpanel } from '~~/lib/core/composables/mp' import { useIsSmallerOrEqualThanBreakpoint } from '~~/composables/browser' import { useEmbed } from '~/lib/viewer/composables/setup/embed' import { useViewerTour } from '~/lib/viewer/composables/tour' -import { onKeyStroke } from '@vueuse/core' +import { onKeyStroke, useEventListener, useResizeObserver } from '@vueuse/core' import { useFunctionRunsStatusSummary } from '~/lib/automate/composables/runStatus' // const isGendoEnabled = useIsAutomateModuleEnabled() // Not working for some reason, always false const isGendoEnabled = ref(true) +const width = ref(360) +const scrollableControlsContainer = ref(null as Nullable) + +const height = ref(scrollableControlsContainer.value?.clientHeight) //computed(() => scrollableControlsContainer.value?.clientHeight) +const isResizing = ref(false) +const resizeHandle = ref(null) +let startWidth = 0 +let startX = 0 + +const startResizing = (event: MouseEvent) => { + event.preventDefault() + isResizing.value = true + startX = event.clientX + startWidth = width.value +} + +if (process.client) { + useResizeObserver(scrollableControlsContainer, (entries) => { + // const entry = entries[0] + const { height: newHeight } = entries[0].contentRect + height.value = newHeight + }) + useEventListener(resizeHandle, 'mousedown', startResizing) + + useEventListener(document, 'mousemove', (event) => { + if (isResizing.value) { + const diffX = event.clientX - startX + width.value = Math.max( + 300, + Math.min(startWidth + diffX, (parseInt('75vw') * window.innerWidth) / 100) + ) + } + }) + + useEventListener(document, 'mouseup', () => { + if (isResizing.value) { + isResizing.value = false + } + }) +} + type ActiveControl = | 'none' | 'models' @@ -303,7 +364,6 @@ const openAddModel = ref(false) const activeControl = ref('models') -const scrollableControlsContainer = ref(null as Nullable) const { diff: { enabled } } = useInjectedViewerInterfaceState() diff --git a/packages/frontend-2/components/viewer/gendo/Item.vue b/packages/frontend-2/components/viewer/gendo/Item.vue index e27939b0a6..76090e07a2 100644 --- a/packages/frontend-2/components/viewer/gendo/Item.vue +++ b/packages/frontend-2/components/viewer/gendo/Item.vue @@ -11,10 +11,6 @@ v-if="detailedRender.status !== 'COMPLETED'" class="relative w-full h-32 rounded-lg flex items-center justify-center" > -
+
+
@@ -52,13 +61,15 @@ import { useMixpanel } from '~~/lib/core/composables/mp' defineEmits(['close']) const showRemove = ref(false) -const { resourceItems, modelsAndVersionIds } = useInjectedViewerLoadedResources() +const { resourceItems, modelsAndVersionIds, objects } = + useInjectedViewerLoadedResources() const { items } = useInjectedViewerRequestedResources() const open = ref(false) const mp = useMixpanel() const removeModel = async (modelId: string) => { + console.log(modelId) // Convert requested resource string to references to specific models // to ensure remove works even when we have "all" or "$folder" in the URL const builder = SpeckleViewer.ViewerRoute.resourceBuilder() @@ -68,7 +79,8 @@ const removeModel = async (modelId: string) => { builder.addModel(loadedResource.modelId, loadedResource.versionId || undefined) } } else { - builder.addObject(loadedResource.objectId) + if (loadedResource.objectId !== modelId) + builder.addObject(loadedResource.objectId) } } mp.track('Viewer Action', { type: 'action', name: 'federation', action: 'remove' }) @@ -78,4 +90,6 @@ const removeModel = async (modelId: string) => { watch(modelsAndVersionIds, (newVal) => { if (newVal.length <= 1) showRemove.value = false }) + +const removeEnabled = computed(() => items.value.length > 1) diff --git a/packages/frontend-2/components/viewer/resources/ObjectCard.vue b/packages/frontend-2/components/viewer/resources/ObjectCard.vue new file mode 100644 index 0000000000..64334533c6 --- /dev/null +++ b/packages/frontend-2/components/viewer/resources/ObjectCard.vue @@ -0,0 +1,48 @@ + + From ae8d8713a18196954290a6e47e7fb1dc1c62f398 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Wed, 29 May 2024 13:44:07 +0100 Subject: [PATCH 19/27] feat(dataviewer): adds selected object support --- .../components/viewer/dataviewer/Panel.vue | 31 ++++++++----------- .../components/viewer/resources/List.vue | 1 - 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/packages/frontend-2/components/viewer/dataviewer/Panel.vue b/packages/frontend-2/components/viewer/dataviewer/Panel.vue index 9573ba5691..e0555f42ed 100644 --- a/packages/frontend-2/components/viewer/dataviewer/Panel.vue +++ b/packages/frontend-2/components/viewer/dataviewer/Panel.vue @@ -14,31 +14,26 @@ diff --git a/packages/frontend-2/components/viewer/resources/List.vue b/packages/frontend-2/components/viewer/resources/List.vue index 2a5f8f1eef..2cfe4d5fe0 100644 --- a/packages/frontend-2/components/viewer/resources/List.vue +++ b/packages/frontend-2/components/viewer/resources/List.vue @@ -69,7 +69,6 @@ const open = ref(false) const mp = useMixpanel() const removeModel = async (modelId: string) => { - console.log(modelId) // Convert requested resource string to references to specific models // to ensure remove works even when we have "all" or "$folder" in the URL const builder = SpeckleViewer.ViewerRoute.resourceBuilder() From 04cdc59c8e6e5ea92decacf5488ee057045e20a2 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Wed, 29 May 2024 14:40:08 +0100 Subject: [PATCH 20/27] feat(dataviewer): removes button from main sidebar, integrates with explorer --- .../frontend-2/components/viewer/Controls.vue | 5 +- .../components/viewer/dataviewer/Panel.vue | 8 +-- .../components/viewer/explorer/Explorer.vue | 64 +++++++++++++------ 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/packages/frontend-2/components/viewer/Controls.vue b/packages/frontend-2/components/viewer/Controls.vue index f291cba812..7b3322cc93 100644 --- a/packages/frontend-2/components/viewer/Controls.vue +++ b/packages/frontend-2/components/viewer/Controls.vue @@ -29,13 +29,14 @@ - + - - - { const localKvps = [] for (const key of keys) { // if (!obj[key]) continue // TODO: deal with null/undef + const value = obj[key] || obj[key] === 0 ? obj[key] : 'null' localKvps.push({ key, - value: obj[key] || 'null', - type: Array.isArray(obj[key]) ? 'array' : typeof obj[key] + value, + type: Array.isArray(value) ? 'array' : typeof value }) } return localKvps From ff138218337288ccffbe25da381881bcc2aa95de Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Wed, 29 May 2024 15:28:43 +0100 Subject: [PATCH 22/27] feat(dataviewer): linting fixes --- packages/frontend-2/components/viewer/Controls.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend-2/components/viewer/Controls.vue b/packages/frontend-2/components/viewer/Controls.vue index 7e3cd0ef6d..086d4fec60 100644 --- a/packages/frontend-2/components/viewer/Controls.vue +++ b/packages/frontend-2/components/viewer/Controls.vue @@ -265,7 +265,6 @@ import { ArrowsPointingOutIcon, ScissorsIcon, PlusIcon, - CodeBracketIcon, ChevronDoubleRightIcon, ArrowsRightLeftIcon } from '@heroicons/vue/24/outline' From ea1905a43bacd738d8abd21171d2a57d5fc29643 Mon Sep 17 00:00:00 2001 From: andrewwallacespeckle <139135120+andrewwallacespeckle@users.noreply.github.com> Date: Thu, 30 May 2024 12:26:24 +0200 Subject: [PATCH 23/27] feat(dataviewer): show raw viewer within Scene Explorer --- .../frontend-2/components/viewer/Controls.vue | 20 ----- .../components/viewer/dataviewer/Panel.vue | 22 ++---- .../components/viewer/explorer/Explorer.vue | 73 +++++++++++-------- .../components/viewer/layout/Panel.vue | 2 +- .../lib/common/generated/gql/graphql.ts | 4 +- 5 files changed, 50 insertions(+), 71 deletions(-) diff --git a/packages/frontend-2/components/viewer/Controls.vue b/packages/frontend-2/components/viewer/Controls.vue index 086d4fec60..c68f96bbe9 100644 --- a/packages/frontend-2/components/viewer/Controls.vue +++ b/packages/frontend-2/components/viewer/Controls.vue @@ -28,16 +28,6 @@ - - - -
-
- - - -
- - - - -
-
-
- {{ obj.name }} -
- +
+
+
+ {{ obj.name }}
+
- +