MCPcopy Create free account
hub / github.com/github/gh-aw / generatePrompt

Method generatePrompt

pkg/workflow/compiler_yaml.go:463–748  ·  view source on GitHub ↗
(yaml *strings.Builder, data *WorkflowData, preActivationJobCreated bool, beforeActivationJobs []string)

Source from the content-addressed store, hash-verified

461}
462
463func (c *Compiler) generatePrompt(yaml *strings.Builder, data *WorkflowData, preActivationJobCreated bool, beforeActivationJobs []string) {
464 compilerYamlLog.Printf("Generating prompt for workflow: %s (markdown size: %d bytes)", data.Name, len(data.MarkdownContent))
465
466 // Collect built-in prompt sections (these should be prepended to user prompt)
467 builtinSections := c.collectPromptSections(data)
468 compilerYamlLog.Printf("Collected %d built-in prompt sections", len(builtinSections))
469
470 // NEW APPROACH: Use runtime-import macros for imports without inputs
471 // - Imported markdown without inputs uses runtime-import macros (loaded at runtime)
472 // - Imported markdown with inputs is still inlined (compile-time substitution required)
473 // - Main workflow markdown body uses runtime-import to allow editing without recompilation
474 // This ensures consistency for most imports while maintaining import inputs functionality
475 //
476 // NOTE: When an engine does not support native agent-file handling
477 // (GetCapabilities().NativeAgentFile == false), the agent file content is already present in the
478 // prompt via the standard mechanisms below — no special Step 0 is needed:
479 // - Agent files WITHOUT inputs: path is in data.ImportPaths → included by Step 1b.
480 // - Agent files WITH inputs: content is in data.ImportedMarkdown → included by Step 1a.
481 // - inlined-imports mode: data.AgentFile is cleared; content is in data.ImportPaths.
482 // All current engines (Claude, Codex, Gemini, Copilot) use this mechanism: NativeAgentFile is false,
483 // and they read the fully-assembled prompt.txt in GetExecutionSteps.
484
485 var userPromptChunks []string
486 var expressionMappings []*ExpressionMapping
487
488 // Step 1a/1b: Process imports in declaration order, interleaving:
489 // - compile-time inlined markdown (imports with inputs)
490 // - runtime-import macros (imports without inputs)
491 // In older workflow data (without PromptImports), fall back to legacy grouped handling.
492 if len(data.PromptImports) > 0 {
493 compilerYamlLog.Printf("Processing %d ordered prompt import entries", len(data.PromptImports))
494 workspaceRoot := ""
495 hasImportInputs := len(data.ImportInputs) > 0
496 if data.InlinedImports && c.markdownPath != "" {
497 workspaceRoot = resolveWorkspaceRoot(c.markdownPath)
498 }
499 for _, entry := range data.PromptImports {
500 if entry.Markdown != "" {
501 cleaned := removeXMLComments(entry.Markdown)
502 if hasImportInputs {
503 cleaned = SubstituteImportInputs(cleaned, data.ImportInputs)
504 }
505 chunks, exprMaps := extractPromptChunksFromMarkdown(cleaned)
506 userPromptChunks = append(userPromptChunks, chunks...)
507 expressionMappings = append(expressionMappings, exprMaps...)
508 continue
509 }
510 if entry.ImportPath == "" {
511 continue
512 }
513 importPath := filepath.ToSlash(entry.ImportPath)
514 if workspaceRoot != "" {
515 rawContent, err := os.ReadFile(filepath.Join(workspaceRoot, importPath))
516 if err != nil {
517 compilerYamlLog.Printf("Warning: failed to read import file %s (%v), falling back to runtime-import", importPath, err)
518 userPromptChunks = append(userPromptChunks, fmt.Sprintf("{{#runtime-import %s}}", importPath))
519 continue
520 }