@weirdfingers/baseboards 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/dist/index.js +131 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/api/alembic/env.py +9 -1
- package/templates/api/alembic/versions/20250101_000000_initial_schema.py +107 -49
- package/templates/api/alembic/versions/20251022_174729_remove_provider_name_from_generations.py +7 -3
- package/templates/api/alembic/versions/20251023_165852_switch_to_declarative_base_and_mapping.py +57 -1
- package/templates/api/alembic/versions/20251202_000000_add_artifact_lineage.py +134 -0
- package/templates/api/alembic/versions/2025925_62735_add_seed_data_for_default_tenant.py +8 -5
- package/templates/api/config/generators.yaml +111 -0
- package/templates/api/src/boards/__init__.py +1 -1
- package/templates/api/src/boards/api/app.py +2 -1
- package/templates/api/src/boards/api/endpoints/tenant_registration.py +1 -1
- package/templates/api/src/boards/api/endpoints/uploads.py +150 -0
- package/templates/api/src/boards/auth/factory.py +1 -1
- package/templates/api/src/boards/dbmodels/__init__.py +8 -22
- package/templates/api/src/boards/generators/artifact_resolution.py +45 -12
- package/templates/api/src/boards/generators/implementations/fal/audio/__init__.py +16 -1
- package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_music_generation.py +171 -0
- package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_sound_effect_generation.py +167 -0
- package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_sound_effects_v2.py +194 -0
- package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_tts_eleven_v3.py +209 -0
- package/templates/api/src/boards/generators/implementations/fal/audio/fal_elevenlabs_tts_turbo_v2_5.py +206 -0
- package/templates/api/src/boards/generators/implementations/fal/audio/fal_minimax_speech_26_hd.py +237 -0
- package/templates/api/src/boards/generators/implementations/fal/audio/minimax_speech_2_6_turbo.py +1 -1
- package/templates/api/src/boards/generators/implementations/fal/image/__init__.py +30 -0
- package/templates/api/src/boards/generators/implementations/fal/image/clarity_upscaler.py +220 -0
- package/templates/api/src/boards/generators/implementations/fal/image/crystal_upscaler.py +173 -0
- package/templates/api/src/boards/generators/implementations/fal/image/fal_ideogram_character.py +227 -0
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2.py +203 -0
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_edit.py +230 -0
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro.py +204 -0
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro_edit.py +221 -0
- package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image.py +177 -0
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_edit_image.py +182 -0
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_mini.py +167 -0
- package/templates/api/src/boards/generators/implementations/fal/image/ideogram_character_edit.py +299 -0
- package/templates/api/src/boards/generators/implementations/fal/image/ideogram_v2.py +190 -0
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro_edit.py +226 -0
- package/templates/api/src/boards/generators/implementations/fal/image/qwen_image.py +249 -0
- package/templates/api/src/boards/generators/implementations/fal/image/qwen_image_edit.py +244 -0
- package/templates/api/src/boards/generators/implementations/fal/video/__init__.py +42 -0
- package/templates/api/src/boards/generators/implementations/fal/video/bytedance_seedance_v1_pro_text_to_video.py +209 -0
- package/templates/api/src/boards/generators/implementations/fal/video/creatify_lipsync.py +161 -0
- package/templates/api/src/boards/generators/implementations/fal/video/fal_bytedance_seedance_v1_pro_image_to_video.py +222 -0
- package/templates/api/src/boards/generators/implementations/fal/video/fal_minimax_hailuo_02_standard_text_to_video.py +152 -0
- package/templates/api/src/boards/generators/implementations/fal/video/fal_pixverse_lipsync.py +197 -0
- package/templates/api/src/boards/generators/implementations/fal/video/fal_sora_2_text_to_video.py +173 -0
- package/templates/api/src/boards/generators/implementations/fal/video/infinitalk.py +221 -0
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_image_to_video.py +175 -0
- package/templates/api/src/boards/generators/implementations/fal/video/minimax_hailuo_2_3_pro_image_to_video.py +153 -0
- package/templates/api/src/boards/generators/implementations/fal/video/sora2_image_to_video.py +172 -0
- package/templates/api/src/boards/generators/implementations/fal/video/sora_2_image_to_video_pro.py +175 -0
- package/templates/api/src/boards/generators/implementations/fal/video/sora_2_text_to_video_pro.py +163 -0
- package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2_pro.py +155 -0
- package/templates/api/src/boards/generators/implementations/fal/video/veed_lipsync.py +174 -0
- package/templates/api/src/boards/generators/implementations/fal/video/veo3.py +194 -0
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_first_last_frame_to_video.py +1 -1
- package/templates/api/src/boards/generators/implementations/fal/video/wan_pro_image_to_video.py +158 -0
- package/templates/api/src/boards/graphql/access_control.py +1 -1
- package/templates/api/src/boards/graphql/mutations/root.py +16 -4
- package/templates/api/src/boards/graphql/resolvers/board.py +0 -2
- package/templates/api/src/boards/graphql/resolvers/generation.py +10 -233
- package/templates/api/src/boards/graphql/resolvers/lineage.py +381 -0
- package/templates/api/src/boards/graphql/resolvers/upload.py +463 -0
- package/templates/api/src/boards/graphql/types/generation.py +62 -26
- package/templates/api/src/boards/middleware.py +1 -1
- package/templates/api/src/boards/storage/factory.py +2 -2
- package/templates/api/src/boards/tenant_isolation.py +9 -9
- package/templates/api/src/boards/workers/actors.py +10 -1
- package/templates/web/package.json +1 -1
- package/templates/web/src/app/boards/[boardId]/page.tsx +14 -5
- package/templates/web/src/app/lineage/[generationId]/page.tsx +233 -0
- package/templates/web/src/components/boards/ArtifactPreview.tsx +20 -1
- package/templates/web/src/components/boards/UploadArtifact.tsx +253 -0
|
@@ -129,7 +129,7 @@ def ensure_preloaded(obj, attr_name: str, error_msg: str | None = None) -> None:
|
|
|
129
129
|
except Exception as e:
|
|
130
130
|
if "was not loaded" in str(e) or "lazy loading" in str(e):
|
|
131
131
|
msg = error_msg or (
|
|
132
|
-
f"Relationship '{attr_name}' was not preloaded.
|
|
132
|
+
f"Relationship '{attr_name}' was not preloaded. Use selectinload() in the query."
|
|
133
133
|
)
|
|
134
134
|
raise RuntimeError(msg) from e
|
|
135
135
|
# Re-raise other exceptions
|
|
@@ -7,7 +7,7 @@ from uuid import UUID
|
|
|
7
7
|
import strawberry
|
|
8
8
|
|
|
9
9
|
from ..types.board import Board, BoardRole
|
|
10
|
-
from ..types.generation import ArtifactType, Generation
|
|
10
|
+
from ..types.generation import ArtifactType, Generation, UploadArtifactInput
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
# Input types for mutations
|
|
@@ -43,14 +43,17 @@ class AddBoardMemberInput:
|
|
|
43
43
|
|
|
44
44
|
@strawberry.input
|
|
45
45
|
class CreateGenerationInput:
|
|
46
|
-
"""Input for creating a new generation.
|
|
46
|
+
"""Input for creating a new generation.
|
|
47
|
+
|
|
48
|
+
Note: Lineage is now captured automatically via artifact resolution.
|
|
49
|
+
Generator input parameters that reference other generations (as artifact types)
|
|
50
|
+
will be automatically resolved and lineage will be tracked.
|
|
51
|
+
"""
|
|
47
52
|
|
|
48
53
|
board_id: UUID
|
|
49
54
|
generator_name: str
|
|
50
55
|
artifact_type: ArtifactType
|
|
51
56
|
input_params: strawberry.scalars.JSON # type: ignore[reportInvalidTypeForm]
|
|
52
|
-
parent_generation_id: UUID | None = None
|
|
53
|
-
input_generation_ids: list[UUID] | None = None
|
|
54
57
|
|
|
55
58
|
|
|
56
59
|
@strawberry.type
|
|
@@ -134,3 +137,12 @@ class Mutation:
|
|
|
134
137
|
from ..resolvers.generation import regenerate
|
|
135
138
|
|
|
136
139
|
return await regenerate(info, id)
|
|
140
|
+
|
|
141
|
+
@strawberry.mutation(name="uploadArtifact")
|
|
142
|
+
async def upload_artifact(
|
|
143
|
+
self, info: strawberry.Info, input: UploadArtifactInput
|
|
144
|
+
) -> Generation:
|
|
145
|
+
"""Upload an artifact from URL (synchronous)."""
|
|
146
|
+
from ..resolvers.upload import upload_artifact_from_url
|
|
147
|
+
|
|
148
|
+
return await upload_artifact_from_url(info, input)
|
|
@@ -442,8 +442,6 @@ async def resolve_board_generations(
|
|
|
442
442
|
additional_files=gen.additional_files or [],
|
|
443
443
|
input_params=gen.input_params or {},
|
|
444
444
|
output_metadata=gen.output_metadata or {},
|
|
445
|
-
parent_generation_id=gen.parent_generation_id,
|
|
446
|
-
input_generation_ids=gen.input_generation_ids or [],
|
|
447
445
|
external_job_id=gen.external_job_id,
|
|
448
446
|
status=GenerationStatus(gen.status),
|
|
449
447
|
progress=float(gen.progress or 0.0),
|
|
@@ -81,8 +81,6 @@ async def resolve_generation_by_id(info: strawberry.Info, id: UUID) -> Generatio
|
|
|
81
81
|
additional_files=gen.additional_files or [],
|
|
82
82
|
input_params=gen.input_params or {},
|
|
83
83
|
output_metadata=gen.output_metadata or {},
|
|
84
|
-
parent_generation_id=gen.parent_generation_id,
|
|
85
|
-
input_generation_ids=gen.input_generation_ids or [],
|
|
86
84
|
external_job_id=gen.external_job_id,
|
|
87
85
|
status=GenerationStatus(gen.status),
|
|
88
86
|
progress=float(gen.progress or 0.0),
|
|
@@ -193,8 +191,6 @@ async def resolve_recent_generations(
|
|
|
193
191
|
additional_files=gen.additional_files or [],
|
|
194
192
|
input_params=gen.input_params or {},
|
|
195
193
|
output_metadata=gen.output_metadata or {},
|
|
196
|
-
parent_generation_id=gen.parent_generation_id,
|
|
197
|
-
input_generation_ids=gen.input_generation_ids or [],
|
|
198
194
|
external_job_id=gen.external_job_id,
|
|
199
195
|
status=GenerationStatusEnum(gen.status),
|
|
200
196
|
progress=float(gen.progress or 0.0),
|
|
@@ -275,187 +271,22 @@ async def resolve_generation_user(generation: Generation, info: strawberry.Info)
|
|
|
275
271
|
async def resolve_generation_parent(
|
|
276
272
|
generation: Generation, info: strawberry.Info
|
|
277
273
|
) -> Generation | None:
|
|
278
|
-
"""
|
|
279
|
-
|
|
280
|
-
return None
|
|
281
|
-
|
|
282
|
-
auth_context = await get_auth_context_from_info(info)
|
|
283
|
-
|
|
284
|
-
async with get_async_session() as session:
|
|
285
|
-
# Query parent generation
|
|
286
|
-
stmt = select(Generations).where(Generations.id == generation.parent_generation_id)
|
|
287
|
-
result = await session.execute(stmt)
|
|
288
|
-
parent = result.scalar_one_or_none()
|
|
289
|
-
|
|
290
|
-
if not parent:
|
|
291
|
-
logger.warning(
|
|
292
|
-
"Parent generation not found",
|
|
293
|
-
parent_id=str(generation.parent_generation_id),
|
|
294
|
-
)
|
|
295
|
-
return None
|
|
296
|
-
|
|
297
|
-
# Check access to parent's board
|
|
298
|
-
board_stmt = (
|
|
299
|
-
select(Boards)
|
|
300
|
-
.where(Boards.id == parent.board_id)
|
|
301
|
-
.options(selectinload(Boards.board_members))
|
|
302
|
-
)
|
|
303
|
-
board_result = await session.execute(board_stmt)
|
|
304
|
-
board = board_result.scalar_one_or_none()
|
|
305
|
-
|
|
306
|
-
if not board or not can_access_board(board, auth_context):
|
|
307
|
-
logger.info(
|
|
308
|
-
"Access denied to parent generation",
|
|
309
|
-
parent_id=str(generation.parent_generation_id),
|
|
310
|
-
)
|
|
311
|
-
return None
|
|
312
|
-
|
|
313
|
-
# Convert to GraphQL type
|
|
314
|
-
from ..types.generation import ArtifactType, GenerationStatus
|
|
315
|
-
from ..types.generation import Generation as GenerationType
|
|
316
|
-
|
|
317
|
-
return GenerationType(
|
|
318
|
-
id=parent.id,
|
|
319
|
-
tenant_id=parent.tenant_id,
|
|
320
|
-
board_id=parent.board_id,
|
|
321
|
-
user_id=parent.user_id,
|
|
322
|
-
generator_name=parent.generator_name,
|
|
323
|
-
artifact_type=ArtifactType(parent.artifact_type),
|
|
324
|
-
storage_url=parent.storage_url,
|
|
325
|
-
thumbnail_url=parent.thumbnail_url,
|
|
326
|
-
additional_files=parent.additional_files or [],
|
|
327
|
-
input_params=parent.input_params or {},
|
|
328
|
-
output_metadata=parent.output_metadata or {},
|
|
329
|
-
parent_generation_id=parent.parent_generation_id,
|
|
330
|
-
input_generation_ids=parent.input_generation_ids or [],
|
|
331
|
-
external_job_id=parent.external_job_id,
|
|
332
|
-
status=GenerationStatus(parent.status),
|
|
333
|
-
progress=float(parent.progress or 0.0),
|
|
334
|
-
error_message=parent.error_message,
|
|
335
|
-
started_at=parent.started_at,
|
|
336
|
-
completed_at=parent.completed_at,
|
|
337
|
-
created_at=parent.created_at,
|
|
338
|
-
updated_at=parent.updated_at,
|
|
339
|
-
)
|
|
274
|
+
"""DEPRECATED: Use ancestry field instead. This resolver is no longer used."""
|
|
275
|
+
return None
|
|
340
276
|
|
|
341
277
|
|
|
342
278
|
async def resolve_generation_inputs(
|
|
343
279
|
generation: Generation, info: strawberry.Info
|
|
344
280
|
) -> list[Generation]: # noqa: E501
|
|
345
|
-
"""
|
|
346
|
-
|
|
347
|
-
return []
|
|
348
|
-
|
|
349
|
-
auth_context = await get_auth_context_from_info(info)
|
|
350
|
-
|
|
351
|
-
async with get_async_session() as session:
|
|
352
|
-
# Query input generations
|
|
353
|
-
stmt = select(Generations).where(Generations.id.in_(generation.input_generation_ids))
|
|
354
|
-
result = await session.execute(stmt)
|
|
355
|
-
inputs = result.scalars().all()
|
|
356
|
-
|
|
357
|
-
# Filter by board access
|
|
358
|
-
accessible_inputs = []
|
|
359
|
-
for input_gen in inputs:
|
|
360
|
-
board_stmt = (
|
|
361
|
-
select(Boards)
|
|
362
|
-
.where(Boards.id == input_gen.board_id)
|
|
363
|
-
.options(selectinload(Boards.board_members))
|
|
364
|
-
)
|
|
365
|
-
board_result = await session.execute(board_stmt)
|
|
366
|
-
board = board_result.scalar_one_or_none()
|
|
367
|
-
|
|
368
|
-
if board and can_access_board(board, auth_context):
|
|
369
|
-
accessible_inputs.append(input_gen)
|
|
370
|
-
|
|
371
|
-
# Convert to GraphQL types
|
|
372
|
-
from ..types.generation import ArtifactType, GenerationStatus
|
|
373
|
-
from ..types.generation import Generation as GenerationType
|
|
374
|
-
|
|
375
|
-
return [
|
|
376
|
-
GenerationType(
|
|
377
|
-
id=gen.id,
|
|
378
|
-
tenant_id=gen.tenant_id,
|
|
379
|
-
board_id=gen.board_id,
|
|
380
|
-
user_id=gen.user_id,
|
|
381
|
-
generator_name=gen.generator_name,
|
|
382
|
-
artifact_type=ArtifactType(gen.artifact_type),
|
|
383
|
-
storage_url=gen.storage_url,
|
|
384
|
-
thumbnail_url=gen.thumbnail_url,
|
|
385
|
-
additional_files=gen.additional_files or [],
|
|
386
|
-
input_params=gen.input_params or {},
|
|
387
|
-
output_metadata=gen.output_metadata or {},
|
|
388
|
-
parent_generation_id=gen.parent_generation_id,
|
|
389
|
-
input_generation_ids=gen.input_generation_ids or [],
|
|
390
|
-
external_job_id=gen.external_job_id,
|
|
391
|
-
status=GenerationStatus(gen.status),
|
|
392
|
-
progress=float(gen.progress or 0.0),
|
|
393
|
-
error_message=gen.error_message,
|
|
394
|
-
started_at=gen.started_at,
|
|
395
|
-
completed_at=gen.completed_at,
|
|
396
|
-
created_at=gen.created_at,
|
|
397
|
-
updated_at=gen.updated_at,
|
|
398
|
-
)
|
|
399
|
-
for gen in accessible_inputs
|
|
400
|
-
]
|
|
281
|
+
"""DEPRECATED: Use input_artifacts field instead. This resolver is no longer used."""
|
|
282
|
+
return []
|
|
401
283
|
|
|
402
284
|
|
|
403
285
|
async def resolve_generation_children(
|
|
404
286
|
generation: Generation, info: strawberry.Info
|
|
405
287
|
) -> list[Generation]: # noqa: E501
|
|
406
|
-
"""
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
async with get_async_session() as session:
|
|
410
|
-
# Query child generations
|
|
411
|
-
stmt = select(Generations).where(Generations.parent_generation_id == generation.id)
|
|
412
|
-
result = await session.execute(stmt)
|
|
413
|
-
children = result.scalars().all()
|
|
414
|
-
|
|
415
|
-
# Filter by board access
|
|
416
|
-
accessible_children = []
|
|
417
|
-
for child_gen in children:
|
|
418
|
-
board_stmt = (
|
|
419
|
-
select(Boards)
|
|
420
|
-
.where(Boards.id == child_gen.board_id)
|
|
421
|
-
.options(selectinload(Boards.board_members))
|
|
422
|
-
)
|
|
423
|
-
board_result = await session.execute(board_stmt)
|
|
424
|
-
board = board_result.scalar_one_or_none()
|
|
425
|
-
|
|
426
|
-
if board and can_access_board(board, auth_context):
|
|
427
|
-
accessible_children.append(child_gen)
|
|
428
|
-
|
|
429
|
-
# Convert to GraphQL types
|
|
430
|
-
from ..types.generation import ArtifactType, GenerationStatus
|
|
431
|
-
from ..types.generation import Generation as GenerationType
|
|
432
|
-
|
|
433
|
-
return [
|
|
434
|
-
GenerationType(
|
|
435
|
-
id=gen.id,
|
|
436
|
-
tenant_id=gen.tenant_id,
|
|
437
|
-
board_id=gen.board_id,
|
|
438
|
-
user_id=gen.user_id,
|
|
439
|
-
generator_name=gen.generator_name,
|
|
440
|
-
artifact_type=ArtifactType(gen.artifact_type),
|
|
441
|
-
storage_url=gen.storage_url,
|
|
442
|
-
thumbnail_url=gen.thumbnail_url,
|
|
443
|
-
additional_files=gen.additional_files or [],
|
|
444
|
-
input_params=gen.input_params or {},
|
|
445
|
-
output_metadata=gen.output_metadata or {},
|
|
446
|
-
parent_generation_id=gen.parent_generation_id,
|
|
447
|
-
input_generation_ids=gen.input_generation_ids or [],
|
|
448
|
-
external_job_id=gen.external_job_id,
|
|
449
|
-
status=GenerationStatus(gen.status),
|
|
450
|
-
progress=float(gen.progress or 0.0),
|
|
451
|
-
error_message=gen.error_message,
|
|
452
|
-
started_at=gen.started_at,
|
|
453
|
-
completed_at=gen.completed_at,
|
|
454
|
-
created_at=gen.created_at,
|
|
455
|
-
updated_at=gen.updated_at,
|
|
456
|
-
)
|
|
457
|
-
for gen in accessible_children
|
|
458
|
-
]
|
|
288
|
+
"""DEPRECATED: Use descendants field instead. This resolver is no longer used."""
|
|
289
|
+
return []
|
|
459
290
|
|
|
460
291
|
|
|
461
292
|
# Mutation resolvers
|
|
@@ -499,50 +330,9 @@ async def create_generation(info: strawberry.Info, input: CreateGenerationInput)
|
|
|
499
330
|
if generator is None:
|
|
500
331
|
raise RuntimeError(f"Unknown generator: {input.generator_name}")
|
|
501
332
|
|
|
502
|
-
# Verify access to parent generation if provided
|
|
503
|
-
if input.parent_generation_id:
|
|
504
|
-
parent_stmt = select(Generations).where(Generations.id == input.parent_generation_id)
|
|
505
|
-
parent_result = await session.execute(parent_stmt)
|
|
506
|
-
parent_gen = parent_result.scalar_one_or_none()
|
|
507
|
-
|
|
508
|
-
if not parent_gen:
|
|
509
|
-
raise RuntimeError("Parent generation not found")
|
|
510
|
-
|
|
511
|
-
# Check access to parent's board
|
|
512
|
-
parent_board_stmt = (
|
|
513
|
-
select(Boards)
|
|
514
|
-
.where(Boards.id == parent_gen.board_id)
|
|
515
|
-
.options(selectinload(Boards.board_members))
|
|
516
|
-
)
|
|
517
|
-
parent_board_result = await session.execute(parent_board_stmt)
|
|
518
|
-
parent_board = parent_board_result.scalar_one_or_none()
|
|
519
|
-
|
|
520
|
-
if not parent_board or not can_access_board(parent_board, auth_context):
|
|
521
|
-
raise RuntimeError("Access denied to parent generation")
|
|
522
|
-
|
|
523
|
-
# Verify access to input generations if provided
|
|
524
|
-
if input.input_generation_ids:
|
|
525
|
-
for input_gen_id in input.input_generation_ids:
|
|
526
|
-
input_stmt = select(Generations).where(Generations.id == input_gen_id)
|
|
527
|
-
input_result = await session.execute(input_stmt)
|
|
528
|
-
input_gen = input_result.scalar_one_or_none()
|
|
529
|
-
|
|
530
|
-
if not input_gen:
|
|
531
|
-
raise RuntimeError(f"Input generation {input_gen_id} not found")
|
|
532
|
-
|
|
533
|
-
# Check access to input's board
|
|
534
|
-
input_board_stmt = (
|
|
535
|
-
select(Boards)
|
|
536
|
-
.where(Boards.id == input_gen.board_id)
|
|
537
|
-
.options(selectinload(Boards.board_members))
|
|
538
|
-
)
|
|
539
|
-
input_board_result = await session.execute(input_board_stmt)
|
|
540
|
-
input_board = input_board_result.scalar_one_or_none()
|
|
541
|
-
|
|
542
|
-
if not input_board or not can_access_board(input_board, auth_context):
|
|
543
|
-
raise RuntimeError(f"Access denied to input generation {input_gen_id}")
|
|
544
|
-
|
|
545
333
|
# Create generation record
|
|
334
|
+
# Note: Lineage will be captured automatically during generation processing
|
|
335
|
+
# via artifact resolution in the worker (see actors.py)
|
|
546
336
|
gen = await jobs_repo.create_generation(
|
|
547
337
|
session,
|
|
548
338
|
tenant_id=auth_context.tenant_id,
|
|
@@ -553,12 +343,6 @@ async def create_generation(info: strawberry.Info, input: CreateGenerationInput)
|
|
|
553
343
|
input_params=input.input_params,
|
|
554
344
|
)
|
|
555
345
|
|
|
556
|
-
# Update parent and input relationships if provided
|
|
557
|
-
if input.parent_generation_id:
|
|
558
|
-
gen.parent_generation_id = input.parent_generation_id
|
|
559
|
-
if input.input_generation_ids:
|
|
560
|
-
gen.input_generation_ids = input.input_generation_ids
|
|
561
|
-
|
|
562
346
|
await session.commit()
|
|
563
347
|
await session.refresh(gen)
|
|
564
348
|
|
|
@@ -595,8 +379,6 @@ async def create_generation(info: strawberry.Info, input: CreateGenerationInput)
|
|
|
595
379
|
additional_files=gen.additional_files or [],
|
|
596
380
|
input_params=gen.input_params or {},
|
|
597
381
|
output_metadata=gen.output_metadata or {},
|
|
598
|
-
parent_generation_id=gen.parent_generation_id,
|
|
599
|
-
input_generation_ids=gen.input_generation_ids or [],
|
|
600
382
|
external_job_id=gen.external_job_id,
|
|
601
383
|
status=GenerationStatus(gen.status),
|
|
602
384
|
progress=float(gen.progress or 0.0),
|
|
@@ -695,8 +477,6 @@ async def cancel_generation(info: strawberry.Info, id: UUID) -> Generation:
|
|
|
695
477
|
additional_files=gen.additional_files or [],
|
|
696
478
|
input_params=gen.input_params or {},
|
|
697
479
|
output_metadata=gen.output_metadata or {},
|
|
698
|
-
parent_generation_id=gen.parent_generation_id,
|
|
699
|
-
input_generation_ids=gen.input_generation_ids or [],
|
|
700
480
|
external_job_id=gen.external_job_id,
|
|
701
481
|
status=GenerationStatus(gen.status),
|
|
702
482
|
progress=float(gen.progress or 0.0),
|
|
@@ -842,9 +622,8 @@ async def regenerate(info: strawberry.Info, id: UUID) -> Generation:
|
|
|
842
622
|
input_params=original.input_params or {},
|
|
843
623
|
)
|
|
844
624
|
|
|
845
|
-
#
|
|
846
|
-
|
|
847
|
-
new_gen.input_generation_ids = original.input_generation_ids or []
|
|
625
|
+
# Note: Lineage will be captured automatically during generation processing
|
|
626
|
+
# via artifact resolution in the worker (see actors.py)
|
|
848
627
|
|
|
849
628
|
await session.commit()
|
|
850
629
|
await session.refresh(new_gen)
|
|
@@ -876,8 +655,6 @@ async def regenerate(info: strawberry.Info, id: UUID) -> Generation:
|
|
|
876
655
|
additional_files=new_gen.additional_files or [],
|
|
877
656
|
input_params=new_gen.input_params or {},
|
|
878
657
|
output_metadata=new_gen.output_metadata or {},
|
|
879
|
-
parent_generation_id=new_gen.parent_generation_id,
|
|
880
|
-
input_generation_ids=new_gen.input_generation_ids or [],
|
|
881
658
|
external_job_id=new_gen.external_job_id,
|
|
882
659
|
status=GenerationStatus(new_gen.status),
|
|
883
660
|
progress=float(new_gen.progress or 0.0),
|