Μετάβαση στο περιεχόμενο

Βήματα pipeline

Ένα βήμα pipeline έχει δύο ανεξάρτητους άξονες:

  • Είδος (StepKind) — πώς ο μηχανισμός προγραμματίζει το βήμα σε σχέση με τα εναύσματά του.
  • Κλειδί σώματος (BuiltInBodyKeys) — ποιο καταχωρισμένο κλείσιμο σώματος εκτελεί την εργασία του βήματος.

Ορίζονται στο packages/cc_domain/lib/features/pipelines/domain/entities/step_kind.dart.

Είδος Σημασιολογία προγραμματισμού
trigger Υποχρεωτικό σημείο εισόδου — ακριβώς ένα ανά πρότυπο, πάντα ο πρώτος κόμβος. Δεν εκτελεί το ίδιο καμία εργασία· το τι ξεκινά την εκτέλεση (χειροκίνητα / γεγονός / χρονοδιάγραμμα) παρακολουθείται ξεχωριστά ως εγγραφές PipelineTrigger. Το σώμα του είναι το pipeline.trigger, που δεν κάνει τίποτα.
listen Ενεργοποιείται όταν ολοκληρωθούν όλα τα βήματα προέλευσης (στο StepTrigger.sourceStepIds).
join Ενεργοποιείται όταν όλα τα βήματα στο waitForStepIds φτάσουν σε τελική κατάσταση.
router Διακλάδωση υπό συνθήκη — το σώμα επιστρέφει StepResult.route(key), που ενεργοποιεί μόνο την κατάντη ακμή της οποίας το routeKey ταιριάζει· οι μη επιλεγμένοι κλάδοι σημειώνονται ως παραλειφθέντες.
forEach Προγραμματίζεται όπως το listen (ενεργοποιείται όταν ολοκληρωθούν όλα τα sourceStepIds). Το καταχωρισμένο σώμα flow.forEach είναι αυτό που επαναλαμβάνει· ο μηχανισμός δεν δημιουργεί ένα θυγατρικό βήμα ανά στοιχείο.
terminal Φρουρός του χρονοπρογραμματιστή χωρίς σώμα. Η εκτέλεση του pipeline ολοκληρώνεται όταν τελειώσει ένα βήμα terminal.

Καταχωρισμένα κλεισίματα σωμάτων με κλειδί τις σταθερές του BuiltInBodyKeys (packages/cc_domain/lib/features/pipelines/domain/templates/builtin_template_seeds.dart). Υπάρχουν 25 και παρατίθενται όλα παρακάτω. Η διαμόρφωση διαβάζεται από το PipelineNodeConfig του βήματος (δείτε παρακάτω), εκτός αν σημειώνεται κάτι διαφορετικό· τα «κλειδιά κατάστασης» διαβάζονται από την κατάσταση του pipeline / το ωφέλιμο φορτίο του εναύσματος κατά τον χρόνο εκτέλεσης.

Ένα βήμα του οποίου το bodyKey δεν είναι καταχωρισμένο παράγει προειδοποίηση κατά τη φόρτωση του προτύπου και έπειτα δεν εκτελείται ποτέ — δεν αποτυγχάνει την εκτέλεση. Τα βήματα trigger και terminal εξαιρούνται από αυτή την προειδοποίηση: το έναυσμα εκτελεί και πάλι το σώμα pipeline.trigger που δεν κάνει τίποτα· ένα βήμα terminal δεν έχει σώμα.

Σώμα που δεν κάνει τίποτα για τον υποχρεωτικό κόμβο trigger — ολοκληρώνεται αμέσως, ώστε ο μηχανισμός να απλωθεί στους κατάντη ακροατές. Καμία διαμόρφωση.

Βήμα κελύφους χωρίς πράκτορα (bash -c). Τα σύμβολα θέσης {{key}} στο σενάριο αντικαθίστανται από την κατάσταση + το ωφέλιμο φορτίο του εναύσματος με τιμές διαφυγής κελύφους.

Πεδίο διαμόρφωσης Περιγραφή
script Εντολή κελύφους προς εκτέλεση (απαιτείται)
outputKey Κλειδί κατάστασης που λαμβάνει το stdout χωρίς περιττά κενά, σε έξοδο 0

Εκτελείται με cwd <cc_root>/pipelines/<pipelineRunId>/ (κοινόχρηστο για όλα τα βήματα bash μιας εκτέλεσης) και με το GITHUB_TOKEN στο περιβάλλον. Γράφει επίσης το <stepId>_runDir στην κατάσταση. Έξοδος διάφορη του μηδενός αποτυγχάνει το βήμα με την ουρά του stderr.

Γενικός κόμβος προτροπής και αποστολής: αποδίδει την προτροπή, αποστέλλει τον πράκτορα σε μια συνομιλία και αναστέλλεται μέχρι να ολοκληρωθεί η εκτέλεση. Το ωφέλιμο φορτίο submit_output του πράκτορα συλλέγεται στην κατάσταση κάτω από το outputKey.

Πεδίο διαμόρφωσης Περιγραφή
agentId UUID πράκτορα με εμβέλεια χώρου εργασίας προς αποστολή (απαιτείται)
prompt Κείμενο οδηγίας· υποστηρίζει αντικατάσταση {{key}} (απαιτείται)
outputKey Κλειδί κατάστασης για τη συλλεγμένη έξοδο
outputSchema JSON Schema που πρέπει να ικανοποιεί η έξοδος
label Ετικέτα εμφάνισης στον καμβά
extras.spaceId Υπάρχουσα συνομιλία στην οποία θα εργαστεί (προεπιλογή: μια κρυφή)
extras.conversationTitle Ονομασμένη ροή μέσα σε αυτόν τον χώρο (προαιρετικά)
extras.mode Διαβάζεται στον κόμβο που ανοίγει το δωμάτιο (messaging.createSpace), όχι εδώ. Προεπιλογή review.

Σώμα δρομολογητή — διαβάζει το config.extras, αξιολογεί μια συνθήκη και επιστρέφει StepResult.route(key). Οι συνθήκες δεν είναι εκφράσεις JavaScript· υποστηρίζονται τρεις μορφές σύνταξης, με σειρά προτεραιότητας:

  • Δέντρο κατηγορημάτων (extras.predicate) — ένα λογικό δέντρο που δρομολογεί "true" / "false". Κάθε κόμβος είναι ένας χάρτης με ένα type:
    • {"type": "fileExists", "paths": [...], "baseKey": "repo_local_path", "negate": false, "recursive": false} — αληθές όταν οποιαδήποτε από τις δηλωμένες διαδρομές υπάρχει στον δίσκο· το negate το αντιστρέφει· το recursive αναζητά και σε υποφακέλους (παραλείποντας τα .git, node_modules, build, .dart_tool). Οι σχετικές διαδρομές επιλύονται έναντι του state[baseKey] (προεπιλογή repo_local_path), αλλιώς έναντι του καταλόγου χώρου εργασίας ανά εκτέλεση.
    • {"type": "comparison", "left": "{{score}}", "op": "gt", "right": 80} — τελεστές equals, notEquals, contains, exists, notExists, gt, lt· διαβάζει την κατάσταση του pipeline, όχι το σύστημα αρχείων.
    • {"type": "and" | "or", "of": [<predicate>, ...]} — λογικές ομάδες.
    • {"type": "not", "of": <predicate>} — άρνηση.
  • Διακόπτης (extras.switchKey) — {"switchKey": "pr_class", "cases": [...], "default": "standard"}· δρομολογεί στην πρώτη περίπτωση που περιέχει η τιμή κατάστασης χωρίς διάκριση πεζών-κεφαλαίων, αλλιώς στο default.
  • Σύγκριση (παλαιού τύπου κλειδιά κορυφαίου επιπέδου extras.left / extras.op / extras.right) — ισοδύναμη με κατηγόρημα comparison, διατηρημένη για πρότυπα που συντάχθηκαν πριν από το δέντρο.

Οι ακμές που ξεκινούν από τον κόμβο φέρουν ένα routeKey που πρέπει να ταιριάζει με το κλειδί που επιστρέφεται.

Δημοσιεύει τα ενοποιημένα ευρήματα ως σχόλιο ελέγχου PR μέσω του πελάτη PR του GitHub.

Κλειδί κατάστασης Περιγραφή
repo_full_name owner/repo (απαιτείται)
pr_number Αριθμός PR — ακέραιος ή αριθμητική συμβολοσειρά (απαιτείται)
consolidated_findings Σώμα σχολίου (απαιτείται)

Επιστρέφει StepResult.terminal με τα comment_review_id και commented_at στην κατάσταση.

Αναρτά ένα μήνυμα σε έναν χώρο μηνυμάτων μέσω του MessagingPort.

Κλειδί κατάστασης Περιγραφή
space_id Χώρος προορισμού (απαιτείται)
content Σώμα μηνύματος, διαβάζεται αυτολεξεί από την κατάσταση (απαιτείται)

Γράφει τα posted_space_id και posted_at στην κατάσταση.

Αποστέλλει ολόκληρη ομάδα αντί για έναν μόνο πράκτορα και έπειτα αναστέλλεται μέχρι να ολοκληρωθούν οι εκτελέσεις των μελών.

Πεδίο διαμόρφωσης Περιγραφή
teamId Ομάδα με εμβέλεια χώρου εργασίας προς αποστολή (απαιτείται· αμοιβαία αποκλειόμενη με το agentId)
prompt Κείμενο στόχου· υποστηρίζει αντικατάσταση {{key}} (απαιτείται)
dispatchMode allParallel (προεπιλογή — μία εργασία ανά μέλος) ή manager (αποστολή μόνο του επικεφαλής για συντονισμό)
outputKey Κλειδί κατάστασης για τις συλλεγμένες εξόδους των μελών
outputSchema, label, extras.spaceId Όπως για το conversation.promptAgent

Πύλη έγκρισης. Αποστέλλει τον πράκτορα που εγκρίνει σε μια συνομιλία (λειτουργία review) με την προτροπή της πύλης και ένα συμβόλαιο εξόδου {decision, reason} και έπειτα αναστέλλεται μέχρι ο εγκρίνων να υποβάλει μέσω του submit_output.

Πεδίο διαμόρφωσης Περιγραφή
agentId Ο πράκτορας που εγκρίνει (απαιτείται)
prompt Προτροπή της πύλης (προαιρετικά· όταν λείπει, χρησιμοποιείται προεπιλεγμένη)
outputKey Κλειδί κατάστασης για το συλλεγμένο ωφέλιμο φορτίο {decision, reason}
outputSchema Προεπιλέγεται σχήμα έγκρισης (decision: approved / rejected, reason)
label, extras.spaceId Όπως για το conversation.promptAgent

Η πύλη επιλύεται μόνο μέσω του submit_output. Το BuiltInBodyKeys.humanGate, η βιβλιοθήκη τύπων κόμβων και το κείμενο προτροπής ενός ενσωματωμένου προτύπου αναφέρουν τα εργαλεία MCP approve_step και reject_step· κανένα από τα δύο εργαλεία δεν υπάρχει σε κανένα πακέτο ή μητρώο.

Αφαιρεί παρωχημένα απομονωμένα worktree· επιλέγει τη λειτουργία του από το ωφέλιμο φορτίο του εναύσματος. Σέβεται τη σημαία dryRun της εκτέλεσης.

Κλειδί κατάστασης Περιγραφή
ticket_id Απελευθερώνει τα worktree αυτού του εισιτηρίου
repo_full_name + pr_number Απελευθερώνει το εφήμερο worktree του συντάκτη PR
space_id Καταστρέφει τα worktree και τον φάκελο αυτής της συνομιλίας
(κανένα από τα παραπάνω) Σαρώνει τον χώρο εργασίας: καταλόγους που εξαφανίστηκαν, νεκρούς χώρους, ορφανούς φακέλους συνομιλιών

Το outputKey (προαιρετικά) λαμβάνει μια συμβολοσειρά σύνοψης.

Αντιστοίχιση / άπλωμα πάνω σε μια συλλογή κατάστασης: αποδίδει την προτροπή μία φορά ανά στοιχείο και έπειτα αποστέλλει τον πράκτορα μία φορά με αυτές τις προτροπές συνενωμένες (διαχωριστικά ---) και αναστέλλεται μέχρι να ολοκληρωθεί αυτή η εκτέλεση. Μια κενή συλλογή ολοκληρώνεται αμέσως με κενή λίστα. Δεν είναι μία παράλληλη αποστολή ανά στοιχείο.

Πεδίο διαμόρφωσης Περιγραφή
agentId Πράκτορας προς αποστολή ανά στοιχείο (απαιτείται)
prompt Προτροπή ανά στοιχείο· υποστηρίζει αντικατάσταση {{key}} (απαιτείται)
extras.iterableKey Κλειδί κατάστασης που περιέχει τη συλλογή (απαιτείται)
extras.itemKey Κλειδί στο οποίο είναι δεσμευμένο το τρέχον στοιχείο στην προτροπή (προεπιλογή item)
outputKey Κλειδί κατάστασης για τη συλλεγμένη έξοδο (μία αποστολή, όχι λίστα)

Εκτελεί άλλο πρότυπο pipeline ως ένθετο υπο-βήμα (το υπο-pipeline εκτελείται ως θυγατρική εκτέλεση με ορισμένο το parentPipelineRunId). Το βήμα αναστέλλεται μέχρι το θυγατρικό να φτάσει σε τελική κατάσταση και έπειτα η τελική κατάσταση του θυγατρικού συγχωνεύεται κάτω από το outputKey.

Πεδίο διαμόρφωσης Περιγραφή
extras.templateId Θυγατρικό πρότυπο προς εκτέλεση (απαιτείται· ένα pipeline δεν μπορεί να καλέσει τον εαυτό του)
inputKeys Κλειδιά κατάστασης που αντιγράφονται στο ωφέλιμο φορτίο του εναύσματος του θυγατρικού
outputKey Κλειδί κατάστασης για τη συγχωνευμένη τελική κατάσταση του θυγατρικού

Ευρετηρίαση tree-sitter στο παρασκήνιο: διατρέχει ένα αποθετήριο, εξάγει σύμβολα/ακμές σε isolates εργατών και τα ενσωματώνει στο γράφημα κώδικα του χώρου εργασίας. Μεταδίδει την πρόοδο στη γραμμή εκτέλεσης του βήματος· υποστηρίζει dry-run. Το tree-sitter και οι γραμματικές του είναι απαιτούμενα native — ένα dylib που λείπει σημαίνει ότι ο διακομιστής δεν ξεκίνησε ποτέ, και μια γραμματική που αποτυγχάνει να επιλυθεί στη μέση της εκτέλεσης αποτυγχάνει το βήμα αντί να το παραλείψει.

Κλειδί κατάστασης Περιγραφή
repo_id Αποθετήριο προς ευρετηρίαση (απαιτείται)
repo_local_path Τοπική διαδρομή του checkout (απαιτείται)

Διαχωρισμός ομιλητών εκτός σύνδεσης. Διαβάζει τον διατηρημένο ήχο της σύσκεψης, τον ομαδοποιεί σε ομιλητές (Person 1, Person 2, …), επαναεπισημαίνει τα τμήματα της μεταγραφής και ξαναγράφει την κατάσταση transcript· εκπέμπει επίσης το diarization_spans για το παράλληλο βήμα meeting.updateTranscript. Περνά τη μεταγραφή αμετάβλητη όταν δεν έχει διατηρηθεί ήχος ή όταν τα μοντέλα δεν είναι εγκατεστημένα.

Κλειδί κατάστασης Περιγραφή
meeting_id Σύσκεψη προς διαχωρισμό ομιλητών (απαιτείται)

Ντετερμινιστικά σώματα αποθήκευσης της σύνοψης σύσκεψης. Καθένα διαβάζει το meeting_id και το δομημένο ωφέλιμο φορτίο meeting_outcome του βήματος πράκτορα ({summary, enhancedNotes, actionItems[], decisions[]}) από την κατάσταση και γράφει το δικό του μέρος στον δικό του πίνακα — σημειώσεις, στοιχεία ενέργειας ή αποφάσεις. Οι ήδη αποθηκευμένες εγγραφές δεν διαγράφονται ποτέ σε υποβαθμισμένη εκτέλεση.

Κλειδί σώματος Περιγραφή
meeting.identifySpeakers Αναγνώριση ομιλητών μεταξύ συσκέψεων: αντιστοιχίζει τους ομιλητές που προέκυψαν από τον διαχωρισμό με αποθηκευμένα προφίλ φωνής και εφαρμόζει αυτόματα τις βέβαιες αντιστοιχίσεις. Δεν κάνει τίποτα χωρίς προφίλ/embeddings.
meeting.updateTranscript Εφαρμόζει τις ετικέτες Person N από το diarization_spans και συγχωνεύει τα θραύσματα ανά παράθυρο σε σειρές ανά ομιλητή, έπειτα αποθηκεύει τη μεταγραφή που καθαρίστηκε. Δεν κάνει τίποτα όταν ο διαχωρισμός δεν παρήγαγε αποτέλεσμα.
meeting.assemblePlayback Συνθέτει το μιξαρισμένο κομμάτι αναπαραγωγής της σύσκεψης από τα διατηρημένα WAV ανά κανάλι. Δεν κάνει τίποτα όταν δεν έχει διατηρηθεί ήχος.
orchestration.markPhase Στο τέλος του DAG εργασίας, γράφει φρουρούς αποτυχίας για υπο-εισιτήρια χωρίς έξοδο και γυρίζει την ενορχήστρωση σε synthesizing.
orchestration.persistDeliverable Γράφει την έξοδο της σύνθεσης στο γονικό εισιτήριο, το ολοκληρώνει, αναρτά το παραδοτέο και σημειώνει την ενορχήστρωση ως completed.
orchestration.awaitApproval Πύλη μερικής έγκρισης: ολοκληρώνεται αμέσως όταν το κλειδί κόμβου του βήματος βρίσκεται στο εγκεκριμένο σύνολο της ενορχήστρωσης, αλλιώς αναστέλλεται μέχρι να το συνεχίσει μεταγενέστερη έγκριση. Είναι το μόνο σώμα που ορίζει το extras.awaitApproval, το οποίο το εξαιρεί από το χρονικό όριο 24 ωρών των βημάτων σε αναστολή.
messaging.createSpace Ανοίγει τη συνομιλία στην οποία εργάζεται το υπόλοιπο πρότυπο, δημοσιευμένη κάτω από το outputKey του βήματος (τα ενσωματωμένα χρησιμοποιούν το pipeline_space_id). Μια κενή λίστα repoIds δεν κάνει checkout τίποτα· το extras['allRepos'] κάνει checkout κάθε αποθετήριο του χώρου εργασίας. Το extras['createConversation'] (απενεργοποιημένο από προεπιλογή) ανοίγει επίσης μια ονομασμένη ροή. Ένα βήμα πράκτορα ΜΠΑΙΝΕΙ σε ένα δωμάτιο και δεν ανοίγει ποτέ δικό του, οπότε ένα άπλωμα χωρίς αυτόν τον κόμβο αποτυγχάνει κατά την αποστολή — και αν τον συνδέσετε μία φορά, όλο το άπλωμα μοιράζεται ένα checkout αντί να προμηθεύεται από ένα για τον καθένα.
prReview.finalize Το τελευταίο βήμα του προτύπου ελέγχου PR: ταξινομεί τους συσσωρευμένους κόμβους ελέγχου σε κάδους συναίνεσης και υπολογίζει την ετυμηγορία ανά PR.
skills.analyze Εκτελεί τη σάρωση εφοδιαστικής αλυσίδας των δεξιοτήτων για τις εγκατεστημένες δεξιότητες ενός χώρου εργασίας και καταγράφει κάθε ετυμηγορία.

Ένα σώμα βήματος επιστρέφει ένα StepResult (packages/cc_domain/lib/features/pipelines/domain/entities/step_result.dart). Όλες οι μέθοδοι κατασκευής δέχονται προαιρετικό χάρτη mutatedState που συγχωνεύεται στην κατάσταση του pipeline, εκτός από το failed.

Μέθοδος κατασκευής Υπογραφή Περιγραφή
ok StepResult.ok({mutatedState}) Κανονική ολοκλήρωση· οι κατάντη ακροατές αξιολογούνται
route StepResult.route(nextRouterKey, {mutatedState}) Ολοκλήρωση δρομολογητή· επιλέγει τον κατάντη κλάδο του οποίου το routeKey ταιριάζει
suspendUntilEvent StepResult.suspendUntilEvent(eventType, {mutatedState}) Παύση μέχρι να ενεργοποιηθεί ένας συγκεκριμένος τύπος γεγονότος τομέα
suspendUntilTasksComplete StepResult.suspendUntilTasksComplete(taskIds, {mutatedState}) Παύση μέχρι όλες οι δηλωμένες εργασίες να φτάσουν σε τελική κατάσταση
terminal StepResult.terminal({mutatedState}) Η εκτέλεση του pipeline ολοκληρώθηκε — δεν υπάρχουν άλλα βήματα
failed StepResult.failed(errorMessage) Το βήμα απέτυχε με μήνυμα σφάλματος

Συμπεριφορά επανάληψης για σώμα κόμβου που αποτυγχάνει (PipelineNodeConfig.retryPolicy· η τιμή null απενεργοποιεί τις επαναλήψεις).

Πεδίο Τύπος Περιγραφή
maxAttempts int Συνολικές προσπάθειες, μαζί με την πρώτη (3 = 1 προσπάθεια + 2 επαναλήψεις)· πρέπει να είναι ≥ 1
backoff String linear ή exponential (προεπιλογή)
initialDelayMs int Καθυστέρηση πριν από την πρώτη επανάληψη, σε χιλιοστά του δευτερολέπτου· οι επόμενες καθυστερήσεις αυξάνονται κατά το backoff

Διαμόρφωση ανά κόμβο που μεταφέρεται μέσα στον ορισμό του βήματος (packages/cc_domain/lib/features/pipelines/domain/entities/pipeline_node_config.dart). Τόσο οι ενσωματωμένοι όσο και οι προσαρμοσμένοι κόμβοι μοιράζονται αυτό το σχήμα· κάθε σώμα διαβάζει μόνο τα πεδία που το αφορούν.

Πεδίο Τύπος Περιγραφή
prompt String? Πρότυπο προτροπής με αντικατάσταση {{key}}
script String? Σώμα σεναρίου Bash με αντικατάσταση {{key}}
agentId String? UUID πράκτορα με εμβέλεια χώρου εργασίας προς αποστολή
inputKeys List<String> Κλειδιά κατάστασης που καταναλώνει ως είσοδο αυτός ο κόμβος
repoIds List<String> Αποθετήρια που κάνει checkout ο κόμβος messaging.createSpace (<repoId> ή <repoId>@<branch>). Κενό = κανένα· extras['allRepos'] = κάθε αποθετήριο του χώρου εργασίας. Αγνοείται σε βήματα πράκτορα.
outputKey String? Κλειδί κατάστασης κάτω από το οποίο γράφεται η έξοδος αυτού του κόμβου
label String? Ετικέτα εμφάνισης στον καμβά (προεπιλογή το αναγνωριστικό του βήματος)
outputSchema Map<String, dynamic>? JSON Schema (υποσύνολο) που πρέπει να ικανοποιεί η τιμή εξόδου
reducer String? Στρατηγική συγχώνευσης όταν παράλληλοι κλάδοι γράφουν στο ίδιο outputKey: append, mergeLists, mergeMaps, sum ή override (προεπιλογή)
retryPolicy StepRetryPolicy? Πολιτική επανάληψης σε αποτυχία του σώματος· null = μία μόνο προσπάθεια
continueOnFail bool Όταν είναι true, μια τελική αποτυχία δεν αποτυγχάνει την εκτέλεση· το σφάλμα αποθηκεύεται κάτω από το state['_stepErrors'][stepId]
timeoutMs int? Χρονικό όριο πραγματικού χρόνου για το σώμα του κόμβου, σε χιλιοστά του δευτερολέπτου· null = χωρίς χρονικό όριο
teamId String? Ομάδα προς αποστολή (κόμβοι team.dispatch)· αμοιβαία αποκλειόμενη με το agentId
dispatchMode String? Λειτουργία εκτέλεσης ομάδας: allParallel ή manager
extras Map<String, dynamic> Διαμόρφωση ελεύθερης μορφής ειδική για το σώμα (π.χ. iterableKey, templateId, δέντρα συνθηκών)

Παράγωγοι προσπελαστές: spaceId (extras['spaceId'] — υπάρχουσα συνομιλία στην οποία θα εργαστεί), createsConversation (extras['createConversation']), conversationTitle (extras['conversationTitle']), modeName (extras['mode'] — chat / review / plan, διαβάζεται στον κόμβο που ανοίγει τον χώρο) και runWhen (extras['runWhen'] — παράλειψη του κόμβου όταν δεν πληρούται).