Run report generation without workspace state
This commit is contained in:
@@ -21,7 +21,6 @@ import (
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/promptexec"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/promptinput"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/report"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/state"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil"
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/weatherdata"
|
||||
)
|
||||
@@ -53,7 +52,6 @@ type GenerateRequest struct {
|
||||
Collector Collector
|
||||
Notifier Notifier
|
||||
Executor promptexec.Executor
|
||||
Store state.Store
|
||||
}
|
||||
|
||||
type BatchRequest struct {
|
||||
@@ -65,7 +63,6 @@ type BatchRequest struct {
|
||||
LLMDebugDir string
|
||||
Collector Collector
|
||||
Executor promptexec.Executor
|
||||
Store state.Store
|
||||
Notifier Notifier
|
||||
}
|
||||
|
||||
@@ -85,21 +82,22 @@ type ReportFacts struct {
|
||||
}
|
||||
|
||||
type ReportResult struct {
|
||||
ModuleSnapshot module.Snapshot
|
||||
ModuleSnapshotPath string
|
||||
DataPackage promptinput.Package
|
||||
DataPackagePath string
|
||||
PreparationPath string
|
||||
ExecutionPath string
|
||||
LLMDebugPath string
|
||||
ReportPath string
|
||||
OutputPath string
|
||||
Metadata state.Metadata
|
||||
MetadataPath string
|
||||
GeneratedTextRawPath string
|
||||
GeneratedTextPath string
|
||||
RenderContextPath string
|
||||
Notification *NotificationResult
|
||||
ReportID report.ID
|
||||
ReportName string
|
||||
PromptID string
|
||||
PromptVersion string
|
||||
RunID string
|
||||
GeneratedAt time.Time
|
||||
Timezone string
|
||||
ValidPeriod timeutil.Period
|
||||
ProfileID string
|
||||
BackendID string
|
||||
ModelName string
|
||||
SourceWarnings []weatherdata.SourceWarning
|
||||
ValidationStatus promptexec.ValidationStatus
|
||||
LLMDebugPath string
|
||||
OutputPath string
|
||||
Notification *NotificationResult
|
||||
}
|
||||
|
||||
type BatchResult struct {
|
||||
@@ -132,25 +130,26 @@ type BatchNotificationReport struct {
|
||||
}
|
||||
|
||||
type BatchReportResult struct {
|
||||
ReportID report.ID `json:"reportId"`
|
||||
ReportName string `json:"reportName"`
|
||||
PromptID string `json:"promptId"`
|
||||
RunID string `json:"runId"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error,omitempty"`
|
||||
NotificationStatus string `json:"notificationStatus,omitempty"`
|
||||
NotificationRunID string `json:"notificationRunId,omitempty"`
|
||||
NotificationPipelineID string `json:"notificationPipelineId,omitempty"`
|
||||
NotificationError string `json:"notificationError,omitempty"`
|
||||
GeneratedAt time.Time `json:"generatedAt"`
|
||||
ValidPeriod timeutil.Period `json:"validPeriod"`
|
||||
DataPackagePath string `json:"dataPackagePath,omitempty"`
|
||||
PreparationPath string `json:"preparationPath,omitempty"`
|
||||
ExecutionPath string `json:"executionPath,omitempty"`
|
||||
LLMDebugPath string `json:"llmDebugPath,omitempty"`
|
||||
ReportPath string `json:"reportPath,omitempty"`
|
||||
OutputPath string `json:"outputPath,omitempty"`
|
||||
MetadataPath string `json:"metadataPath,omitempty"`
|
||||
ReportID report.ID `json:"reportId"`
|
||||
ReportName string `json:"reportName"`
|
||||
PromptID string `json:"promptId"`
|
||||
RunID string `json:"runId"`
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error,omitempty"`
|
||||
NotificationStatus string `json:"notificationStatus,omitempty"`
|
||||
NotificationRunID string `json:"notificationRunId,omitempty"`
|
||||
NotificationPipelineID string `json:"notificationPipelineId,omitempty"`
|
||||
NotificationError string `json:"notificationError,omitempty"`
|
||||
GeneratedAt time.Time `json:"generatedAt"`
|
||||
ValidPeriod timeutil.Period `json:"validPeriod"`
|
||||
Timezone string `json:"timezone"`
|
||||
ProfileID string `json:"profileId,omitempty"`
|
||||
BackendID string `json:"backendId,omitempty"`
|
||||
ModelName string `json:"modelName,omitempty"`
|
||||
SourceWarnings []weatherdata.SourceWarning `json:"sourceWarnings,omitempty"`
|
||||
ValidationStatus promptexec.ValidationStatus `json:"validationStatus,omitempty"`
|
||||
LLMDebugPath string `json:"llmDebugPath,omitempty"`
|
||||
OutputPath string `json:"outputPath,omitempty"`
|
||||
}
|
||||
|
||||
type BatchError struct {
|
||||
@@ -260,14 +259,15 @@ func GenerateDetailed(ctx context.Context, req GenerateRequest) (*ReportResult,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := initialReportResult(req, resolved, PromptInspectionResult{})
|
||||
outputPath, err := resolveReportOutputPath(req.WorkingDir, req.OutputPath, resolved)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return result, err
|
||||
}
|
||||
req.OutputPath = outputPath
|
||||
debugWriter, err := promptdebug.NewPromptDebugWriter(req.LLMDebugDir)
|
||||
if err != nil {
|
||||
return nil, promptexec.NewError(promptexec.InvalidConfiguration, "initialize prompt debug", err)
|
||||
return result, promptexec.NewError(promptexec.InvalidConfiguration, "initialize prompt debug", err)
|
||||
}
|
||||
inspection, err := InspectPromptExecution(ctx, PromptInspectionRequest{
|
||||
Resolved: resolved,
|
||||
@@ -275,11 +275,12 @@ func GenerateDetailed(ctx context.Context, req GenerateRequest) (*ReportResult,
|
||||
Promptkit: req.Config.Promptkit,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return result, err
|
||||
}
|
||||
result.ProfileID, result.BackendID, result.ModelName = inspection.ProfileID, inspection.BackendID, inspection.ModelName
|
||||
collection, err := collectWeather(ctx, req.Config, req.Collector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return result, err
|
||||
}
|
||||
return generatePromptReport(ctx, promptReportRequest{
|
||||
GenerateRequest: req,
|
||||
@@ -287,6 +288,7 @@ func GenerateDetailed(ctx context.Context, req GenerateRequest) (*ReportResult,
|
||||
Collection: *collection,
|
||||
Inspection: inspection,
|
||||
DebugWriter: debugWriter,
|
||||
Result: result,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -339,14 +341,6 @@ func RunBatchDetailed(ctx context.Context, req BatchRequest) (*BatchResult, erro
|
||||
return nil, err
|
||||
}
|
||||
if req.Batch == BatchEvening || req.Batch == BatchMorning {
|
||||
store := req.Store
|
||||
if store == nil {
|
||||
defaultStore, err := defaultStore(req.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
store = defaultStore
|
||||
}
|
||||
startedAt := now
|
||||
result := &BatchResult{Batch: req.Batch, StartedAt: startedAt}
|
||||
for _, planned := range plannedReports {
|
||||
@@ -362,7 +356,6 @@ func RunBatchDetailed(ctx context.Context, req BatchRequest) (*BatchResult, erro
|
||||
OutputPath: outputPath,
|
||||
Notifier: req.Notifier,
|
||||
Executor: req.Executor,
|
||||
Store: store,
|
||||
},
|
||||
Resolved: resolved,
|
||||
Collection: *collection,
|
||||
@@ -398,13 +391,14 @@ func RunBatchDetailed(ctx context.Context, req BatchRequest) (*BatchResult, erro
|
||||
}
|
||||
|
||||
func copyBatchReportPaths(item *BatchReportResult, result *ReportResult) {
|
||||
item.DataPackagePath = result.DataPackagePath
|
||||
item.PreparationPath = result.PreparationPath
|
||||
item.ExecutionPath = result.ExecutionPath
|
||||
item.LLMDebugPath = result.LLMDebugPath
|
||||
item.ReportPath = result.ReportPath
|
||||
item.OutputPath = result.OutputPath
|
||||
item.MetadataPath = result.MetadataPath
|
||||
item.ProfileID = result.ProfileID
|
||||
item.BackendID = result.BackendID
|
||||
item.ModelName = result.ModelName
|
||||
item.Timezone = result.Timezone
|
||||
item.SourceWarnings = append([]weatherdata.SourceWarning(nil), result.SourceWarnings...)
|
||||
item.ValidationStatus = result.ValidationStatus
|
||||
if result.Notification != nil {
|
||||
item.NotificationStatus = result.Notification.Status
|
||||
item.NotificationRunID = result.Notification.RunID
|
||||
@@ -451,6 +445,7 @@ func batchReportResult(planned plannedBatchReport) BatchReportResult {
|
||||
RunID: metadata.RunID,
|
||||
GeneratedAt: metadata.GeneratedAt,
|
||||
ValidPeriod: metadata.ValidPeriod,
|
||||
Timezone: "",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,78 +607,6 @@ func FetchAndSaveBundle(ctx context.Context, req FetchBundleRequest) (*weatherda
|
||||
return bundle, nil
|
||||
}
|
||||
|
||||
type finalizeRenderedReportRequest struct {
|
||||
Config config.Config
|
||||
Store state.Store
|
||||
Resolved report.Resolved
|
||||
Metadata state.Metadata
|
||||
MetadataPath string
|
||||
ExecutionArtifact *state.PromptExecutionArtifact
|
||||
RenderedReportPath string
|
||||
OutputPath string
|
||||
Notifier Notifier
|
||||
GenerationErr error
|
||||
noNotify bool
|
||||
}
|
||||
|
||||
type finalizeRenderedReportResult struct {
|
||||
OutputPath string
|
||||
Metadata state.Metadata
|
||||
MetadataPath string
|
||||
Notification *NotificationResult
|
||||
}
|
||||
|
||||
func finalizeRenderedReport(ctx context.Context, req finalizeRenderedReportRequest) (finalizeRenderedReportResult, error) {
|
||||
if req.Store == nil {
|
||||
return finalizeRenderedReportResult{}, fmt.Errorf("state store is required")
|
||||
}
|
||||
if req.RenderedReportPath == "" {
|
||||
return finalizeRenderedReportResult{}, fmt.Errorf("rendered report path is required for report %q", req.Resolved.Definition.ID)
|
||||
}
|
||||
if req.ExecutionArtifact == nil {
|
||||
return finalizeRenderedReportResult{}, fmt.Errorf("prompt execution artifact is required for report %q", req.Resolved.Definition.ID)
|
||||
}
|
||||
|
||||
result := finalizeRenderedReportResult{Metadata: req.Metadata, MetadataPath: req.MetadataPath}
|
||||
if req.OutputPath != "" && req.GenerationErr == nil {
|
||||
if req.OutputPath != req.RenderedReportPath {
|
||||
if err := fileutil.CopyFileAtomic(req.RenderedReportPath, req.OutputPath); err != nil {
|
||||
return result, err
|
||||
}
|
||||
result.OutputPath = req.OutputPath
|
||||
if err := persistReachedPromptPath(ctx, req.Store, req.Resolved, req.ExecutionArtifact, func(paths *state.PromptExecutionPaths) {
|
||||
paths.OutputPath = req.OutputPath
|
||||
}); err != nil {
|
||||
return result, err
|
||||
}
|
||||
} else {
|
||||
result.OutputPath = req.OutputPath
|
||||
}
|
||||
}
|
||||
|
||||
metadata := req.Metadata
|
||||
metadata.RenderedReportPath = req.RenderedReportPath
|
||||
metadataPath, err := req.Store.SaveMetadata(ctx, metadata)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result.Metadata = metadata
|
||||
result.MetadataPath = metadataPath
|
||||
if req.GenerationErr != nil {
|
||||
return result, req.GenerationErr
|
||||
}
|
||||
if req.noNotify {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
notification, err := notifyReport(ctx, req.Config, req.Resolved, req.OutputPath, metadata.RunID, metadata.GeneratedAt, req.Notifier)
|
||||
result.Notification = notification
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func notifyReport(ctx context.Context, cfg config.Config, resolved report.Resolved, outputPath, runID string, generatedAt time.Time, notifier Notifier) (*NotificationResult, error) {
|
||||
notifier, enabled := reportNotifier(cfg, notifier)
|
||||
if !enabled {
|
||||
@@ -965,7 +888,7 @@ func briefingBuildContext(cfg config.Config, resolved report.Resolved, collected
|
||||
}
|
||||
}
|
||||
|
||||
func promptMetadata(metadata state.Metadata) promptinput.Metadata {
|
||||
func promptMetadata(metadata briefing.Metadata) promptinput.Metadata {
|
||||
return promptinput.Metadata{
|
||||
RunID: metadata.RunID,
|
||||
ReportID: metadata.ReportID,
|
||||
@@ -1008,10 +931,6 @@ func briefingLocation(cfg config.Config) *briefing.LocationContext {
|
||||
return &location
|
||||
}
|
||||
|
||||
func defaultStore(cfg config.Config) (*state.FilesystemStore, error) {
|
||||
return state.NewFilesystemStore(cfg.Workspace)
|
||||
}
|
||||
|
||||
func generatedReportError(resolved report.Resolved, runID string, operation string, err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user