Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@rushstack/rush-reporter",
"comment": "Add Heft integration over a negotiated inherited descriptor: HeftChildEmitter and HeftDescriptorHost with parent/child event correlation, a raw-stream fallback for older Heft, and descriptor allocation helpers",
"type": "minor"
}
],
"packageName": "@rushstack/rush-reporter",
"email": "TheLarkInn@users.noreply.github.com"
}
109 changes: 109 additions & 0 deletions common/reviews/api/rush-reporter.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

```ts

import type { Readable } from 'node:stream';
import type { Writable } from 'node:stream';

// @beta
export class AiReporter implements IReporter {
constructor(options: IAiReporterOptions);
Expand All @@ -19,6 +22,9 @@ export class AiReporter implements IReporter {
report(event: IReporterEventEnvelope<unknown>): void;
}

// @beta
export function allocateChildDescriptor(fdNumber?: number): IChildDescriptorPlan;

// @beta
export const ALREADY_REPORTED_ERROR_NAME: 'AlreadyReportedError';

Expand Down Expand Up @@ -167,6 +173,30 @@ export function getPrivacyClassificationRank(classification: ReporterPrivacyClas
// @beta
export function getSignalExitCode(signal: NodeJS.Signals): number;

// @beta
export class HeftChildEmitter {
constructor(options: IHeftChildEmitterOptions);
emitEvent(input: IHeftChildEventInput): string | undefined;
readonly mode: HeftChildReporterMode;
sendHello(): boolean;
writeRaw(stream: 'stdout' | 'stderr', text: string): void;
}

// @beta
export type HeftChildReporterMode = 'structured' | 'raw-fallback';

// @beta
export class HeftDescriptorHost {
constructor(options: IHeftDescriptorHostOptions);
createStreamProcessor(): {
write(chunk: string): void;
flush(): IHeftChildResult;
};
processChildNdjson(ndjson: string): IHeftChildResult;
processChildRecord(record: unknown): boolean;
processChildRecords(records: readonly unknown[]): IHeftChildResult;
}

// @beta
export interface IAiDiagnostic {
// (undocumented)
Expand Down Expand Up @@ -297,6 +327,13 @@ export interface IBootstrapTruncation {
readonly truncated: boolean;
}

// @beta
export interface IChildDescriptorPlan {
readonly env: Record<string, string>;
readonly fdNumber: number;
readonly stdio: (string | number)[];
}

// @beta
export interface IClassifiedDiagnosticValue {
readonly privacy: ReporterPrivacyClassification;
Expand Down Expand Up @@ -418,6 +455,63 @@ export interface IGetMatchersOptions {
readonly version?: string;
}

// @beta
export interface IHeftChildEmitterOptions {
readonly capabilities?: readonly string[];
readonly childSessionId: string;
readonly env: Record<string, string | undefined>;
readonly now?: () => string;
readonly producerVersion: string;
readonly protocolVersion?: IReporterProtocolVersion;
readonly requiredFeatures?: readonly string[];
readonly source: IReporterEventSource;
readonly writeDescriptor?: (text: string) => void;
readonly writeStderr?: (text: string) => void;
readonly writeStdout?: (text: string) => void;
}

// @beta
export interface IHeftChildEventInput {
// (undocumented)
Comment thread
TheLarkInn marked this conversation as resolved.
readonly payload?: unknown;
// (undocumented)
readonly privacy?: 'public' | 'local-sensitive' | 'secret';
// (undocumented)
readonly scope?: IReporterEventScope;
// (undocumented)
readonly type: ReporterEventType;
}

// @beta
export interface IHeftChildOutputStreams {
readonly stderr: Readable | null;
readonly stdout: Readable | null;
}

// @beta
export interface IHeftChildOutputTargets {
readonly stderr: Writable;
readonly stdout: Writable;
}

// @beta
export interface IHeftChildResult {
readonly accepted: boolean;
readonly ack?: IReporterHelloAck;
readonly diagnostic?: IRushDiagnostic;
readonly eventCount: number;
}

// @beta
export interface IHeftDescriptorHostOptions {
readonly forwardEnvelope: (envelope: IReporterEventEnvelope<unknown>) => void;
readonly onNegotiation?: (result: IReporterHandshakeResult) => void;
readonly parentOperationId?: string;
readonly parentSessionId: string;
readonly supportedCapabilities?: readonly string[];
readonly supportedProtocolVersion: IReporterProtocolVersion;
}

// @beta
export interface IInteractiveTerminal {
readonly columns: number;
Expand Down Expand Up @@ -1131,9 +1225,15 @@ export function readBootstrapHandoffFileAsync(filePath: string): Promise<{
discardedRecordCount: number;
}>;

// @beta
export function readChildDescriptorFd(env: Record<string, string | undefined>): number | undefined;

// @beta
export function regroupOperationOutput(events: readonly IReporterEventEnvelope<unknown>[]): Map<string, string>;

// @beta
export function relayHeftChildOutput(child: IHeftChildOutputStreams, targets?: IHeftChildOutputTargets): void;

// @beta
export function renderActiveProjectsRow(projects: readonly string[], width: number): string;

Expand Down Expand Up @@ -1285,6 +1385,12 @@ export const RUSH_DIAGNOSTIC_CODE_DEFINITIONS: readonly [{
readonly defaultSeverity: "error";
readonly summaryKey: "diagnostic.RUSH_PROTOCOL_UPDATE_REQUIRED.summary";
readonly detailKey: "diagnostic.RUSH_PROTOCOL_UPDATE_REQUIRED.detail";
}, {
readonly code: "RUSH_PROTOCOL_INVALID_CHILD_STREAM";
readonly category: "environment";
readonly defaultSeverity: "error";
readonly summaryKey: "diagnostic.RUSH_PROTOCOL_INVALID_CHILD_STREAM.summary";
readonly detailKey: "diagnostic.RUSH_PROTOCOL_INVALID_CHILD_STREAM.detail";
}, {
readonly code: "RUSH_INTERNAL_UNEXPECTED";
readonly category: "internal";
Expand Down Expand Up @@ -1326,6 +1432,9 @@ export const RUSH_REPORTER_BOOTSTRAP_HANDOFF_ENV_VAR: '_RUSH_REPORTER_BOOTSTRAP_
// @beta
export const RUSH_REPORTER_BOOTSTRAP_NONCE_ENV_VAR: '_RUSH_REPORTER_BOOTSTRAP_NONCE';

// @beta
export const RUSH_REPORTER_CHILD_FD_ENV_VAR: '_RUSH_REPORTER_CHILD_FD';

// @beta
export const RUSH_REPORTER_ENV_VAR: 'RUSH_REPORTER';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ export const RUSH_DIAGNOSTIC_CODE_DEFINITIONS = defineRushDiagnosticCodeDefiniti
summaryKey: 'diagnostic.RUSH_PROTOCOL_UPDATE_REQUIRED.summary',
detailKey: 'diagnostic.RUSH_PROTOCOL_UPDATE_REQUIRED.detail'
},
{
code: 'RUSH_PROTOCOL_INVALID_CHILD_STREAM',
category: 'environment',
defaultSeverity: 'error',
summaryKey: 'diagnostic.RUSH_PROTOCOL_INVALID_CHILD_STREAM.summary',
detailKey: 'diagnostic.RUSH_PROTOCOL_INVALID_CHILD_STREAM.detail'
},
{
code: RUSH_INTERNAL_ERROR_CODE,
category: 'internal',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,8 @@ export const ENVIRONMENT_DIAGNOSTIC_TEMPLATES = {
'diagnostic.RUSH_PROTOCOL_UPDATE_REQUIRED.summary':
'A reporter protocol feature required by {producerVersion} is not supported by this Rush.',
'diagnostic.RUSH_PROTOCOL_UPDATE_REQUIRED.detail':
'The producer advertised protocol major {producerProtocolMajor}. Update your global Rush installation to a version that supports it.'
'The producer advertised protocol major {producerProtocolMajor}. Update your global Rush installation to a version that supports it.',
'diagnostic.RUSH_PROTOCOL_INVALID_CHILD_STREAM.summary':
'A child process sent an invalid reporter protocol stream.',
'diagnostic.RUSH_PROTOCOL_INVALID_CHILD_STREAM.detail': 'The child reporter stream was rejected because {reason}.'
} as const;
Loading