@sous-io/plugin-api 0.0.0-stage → 1.0.1
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/LICENSE +201 -0
- package/README.md +97 -2
- package/dist/command-variables.d.ts +13 -0
- package/dist/command-variables.js +28 -0
- package/dist/config.d.ts +170 -0
- package/dist/config.js +1 -0
- package/dist/context.d.ts +159 -0
- package/dist/context.js +1 -0
- package/dist/entities.d.ts +60 -0
- package/dist/entities.js +1 -0
- package/dist/errors.d.ts +111 -0
- package/dist/errors.js +138 -0
- package/dist/events.d.ts +90 -0
- package/dist/events.js +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +14 -0
- package/dist/intents.d.ts +151 -0
- package/dist/intents.js +1 -0
- package/dist/json.d.ts +84 -0
- package/dist/json.js +7 -0
- package/dist/node.d.ts +81 -0
- package/dist/node.js +1 -0
- package/dist/outputs.d.ts +193 -0
- package/dist/outputs.js +286 -0
- package/dist/plugin.d.ts +144 -0
- package/dist/plugin.js +18 -0
- package/dist/prompter.d.ts +66 -0
- package/dist/prompter.js +32 -0
- package/dist/registry.d.ts +91 -0
- package/dist/registry.js +1 -0
- package/dist/report-styles.d.ts +220 -0
- package/dist/report-styles.js +60 -0
- package/dist/reporter.d.ts +270 -0
- package/dist/reporter.js +388 -0
- package/dist/schema.d.ts +131 -0
- package/dist/schema.js +211 -0
- package/dist/services.d.ts +68 -0
- package/dist/services.js +1 -0
- package/dist/timing.d.ts +31 -0
- package/dist/timing.js +20 -0
- package/package.json +33 -3
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kinds of entry a reporter shows, and the facts each one carries in `details`. A style says what
|
|
3
|
+
* an entry IS, never how it looks: each front end's reporter decides that. A new style is added here
|
|
4
|
+
* when an output needs one, together with its convenience method in `BaseReporter` (reporter.ts),
|
|
5
|
+
* which is the only way callers produce it.
|
|
6
|
+
*
|
|
7
|
+
* Every styled message also carries a plain-text `message`, so a reporter that ignores styles (a
|
|
8
|
+
* log file, a test buffer) still has something readable.
|
|
9
|
+
*/
|
|
10
|
+
/** What kind of entry a reported message is. */
|
|
11
|
+
export declare const ReportEntryStyle: {
|
|
12
|
+
/** A paragraph of text, which a front end may wrap. `details` is optional data. */
|
|
13
|
+
readonly Plain: "plain";
|
|
14
|
+
/** Text shown exactly as given: no wrapping, no color (a value printed for a script to read). No details. */
|
|
15
|
+
readonly Text: "text";
|
|
16
|
+
/** An explanation that is neither a warning nor an error. No details. */
|
|
17
|
+
readonly Note: "note";
|
|
18
|
+
/** The start of an operation, such as "Building the project". {@link OperationStartDetails}. */
|
|
19
|
+
readonly OperationStart: "operation-start";
|
|
20
|
+
/** A step inside the current operation, such as one target being compiled. {@link StepStartDetails}. */
|
|
21
|
+
readonly StepStart: "step-start";
|
|
22
|
+
/** One line of detail inside the current operation or step. No details. */
|
|
23
|
+
readonly Detail: "detail";
|
|
24
|
+
/** One action done (or to be done) to one target, such as a file written. {@link OperationDetails}. */
|
|
25
|
+
readonly Operation: "operation";
|
|
26
|
+
/** How an operation ended, such as "Done." {@link OperationEndDetails}. */
|
|
27
|
+
readonly OperationEnd: "operation-end";
|
|
28
|
+
/** One label and its value. The message is a `VariableSet`. */
|
|
29
|
+
readonly Variable: "variable";
|
|
30
|
+
/** Labels and values, read as one block, under an optional title. The message is a `VariableSet`. */
|
|
31
|
+
readonly VariableList: "variable-list";
|
|
32
|
+
/** The facts a command runs with: the project, its config, ... The message is a `VariableSet`. */
|
|
33
|
+
readonly CommandVariables: "command-variables";
|
|
34
|
+
/** A list of items, with an optional title and closing sentence. The message is an `ItemList`. */
|
|
35
|
+
readonly List: "list";
|
|
36
|
+
/** A table of rows. The message is a `Table`. */
|
|
37
|
+
readonly Table: "table";
|
|
38
|
+
/** Items nested under other items, such as each contributor and the changes it made. The message is a `Tree`. */
|
|
39
|
+
readonly Tree: "tree";
|
|
40
|
+
/** How many things were found. {@link CountDetails}. */
|
|
41
|
+
readonly Count: "count";
|
|
42
|
+
/** Says that a run is a dry run, or what a dry run left undone. No details. */
|
|
43
|
+
readonly DryRun: "dry-run";
|
|
44
|
+
/** Something wrong, with its cause and what to do about it. {@link ProblemDetails}. */
|
|
45
|
+
readonly Problem: "problem";
|
|
46
|
+
/** What a name on the command line resolved to, and why. {@link ResolvedReferenceFacts}. */
|
|
47
|
+
readonly ResolvedReference: "resolved-reference";
|
|
48
|
+
/** The question about to be asked, and where its answer goes. {@link QuestionDetails}. */
|
|
49
|
+
readonly Question: "question";
|
|
50
|
+
/** A command sous runs (or would run). {@link CommandDetails}. */
|
|
51
|
+
readonly Command: "command";
|
|
52
|
+
/** Progress through a longer step. {@link ProgressEvent}. */
|
|
53
|
+
readonly Progress: "progress";
|
|
54
|
+
/** A structured value, such as a command's result as data. The message is a `DataValue`. */
|
|
55
|
+
readonly Data: "data";
|
|
56
|
+
/** The sous banner. No details. */
|
|
57
|
+
readonly Banner: "banner";
|
|
58
|
+
/** A command's result: the message is `IntentOutputs`. */
|
|
59
|
+
readonly Result: "result";
|
|
60
|
+
};
|
|
61
|
+
/** One of the {@link ReportEntryStyle} values. */
|
|
62
|
+
export type ReportEntryStyle = (typeof ReportEntryStyle)[keyof typeof ReportEntryStyle];
|
|
63
|
+
/** {@link ReportEntryStyle.OperationStart}. */
|
|
64
|
+
export interface OperationStartDetails {
|
|
65
|
+
/** What the operation does, in a few words: `Building the project`. */
|
|
66
|
+
readonly name: string;
|
|
67
|
+
}
|
|
68
|
+
/** {@link ReportEntryStyle.StepStart}. */
|
|
69
|
+
export interface StepStartDetails {
|
|
70
|
+
/** What the step does or works on: `CLAUDE.md`. */
|
|
71
|
+
readonly name: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* What was done to a target. The `would-` actions are a dry run's: what a real run would do.
|
|
75
|
+
*
|
|
76
|
+
* - `written`: created or changed.
|
|
77
|
+
* - `unchanged`: already as it should be; nothing written.
|
|
78
|
+
* - `skipped`: left alone on purpose (the note says why).
|
|
79
|
+
* - `failed`: not done because of an error.
|
|
80
|
+
* - `removed`: deleted, such as an output no target produces any more.
|
|
81
|
+
*/
|
|
82
|
+
export type OperationAction = "written" | "would-write" | "unchanged" | "skipped" | "failed" | "removed" | "would-remove";
|
|
83
|
+
/** {@link ReportEntryStyle.Operation}. */
|
|
84
|
+
export interface OperationDetails {
|
|
85
|
+
readonly action: OperationAction;
|
|
86
|
+
/** What the action was done to: usually an absolute file path. */
|
|
87
|
+
readonly target: string;
|
|
88
|
+
/** Why, or anything else worth knowing, in a few words: `left out by the transform "strip"`. */
|
|
89
|
+
readonly note?: string;
|
|
90
|
+
/** For a written file: roughly how many tokens it holds. */
|
|
91
|
+
readonly tokens?: number;
|
|
92
|
+
}
|
|
93
|
+
/** {@link ReportEntryStyle.OperationEnd}. */
|
|
94
|
+
export interface OperationEndDetails {
|
|
95
|
+
/** Whether the operation succeeded. */
|
|
96
|
+
readonly ok: boolean;
|
|
97
|
+
}
|
|
98
|
+
/** One label and its value. */
|
|
99
|
+
export interface VariableEntry {
|
|
100
|
+
/** The name on the left. An empty label continues the entry above. */
|
|
101
|
+
readonly label: string;
|
|
102
|
+
/** The value. */
|
|
103
|
+
readonly value: unknown;
|
|
104
|
+
/** A secondary fact (where it came from), shown less prominently after the value. */
|
|
105
|
+
readonly detail?: string;
|
|
106
|
+
}
|
|
107
|
+
/** What a column holds, which decides how it aligns and where it is cut. */
|
|
108
|
+
export type ColumnKind = "text" | "path" | "url" | "number";
|
|
109
|
+
/** What a column does with a cell too long for it. */
|
|
110
|
+
export type ColumnOverflow = "wrap" | "truncate";
|
|
111
|
+
/** Which end of a cell is given up when it is cut. */
|
|
112
|
+
export type TruncateSide = "start" | "middle" | "end";
|
|
113
|
+
/** Where a cell sits inside its column. */
|
|
114
|
+
export type ColumnAlign = "left" | "right" | "center";
|
|
115
|
+
/** How willingly a column is hidden when there is no room for it. */
|
|
116
|
+
export type ColumnPriority = "low" | "medium" | "high";
|
|
117
|
+
/** One column of a table. Every field after `header` is a hint a front end may ignore. */
|
|
118
|
+
export interface TableColumn {
|
|
119
|
+
/** The property each row is read from. */
|
|
120
|
+
key: string;
|
|
121
|
+
/** The heading shown above the column. */
|
|
122
|
+
header: string;
|
|
123
|
+
/** Whether a long cell wraps onto more lines or is cut. Defaults to wrapping. */
|
|
124
|
+
overflow?: ColumnOverflow;
|
|
125
|
+
/** Which end a cut takes from. Defaults by kind: the middle of a path or a URL, the end of anything else. */
|
|
126
|
+
truncate?: TruncateSide;
|
|
127
|
+
/** What the column holds. Defaults to plain text. */
|
|
128
|
+
kind?: ColumnKind;
|
|
129
|
+
/** Where a cell sits in the column. Defaults to the right for a number, the left for everything else. */
|
|
130
|
+
align?: ColumnAlign;
|
|
131
|
+
/** This column's share of any width left over once every column has its natural width. Defaults to none. */
|
|
132
|
+
flex?: number;
|
|
133
|
+
/** The narrowest this column is ever squeezed to. Defaults to the width of its heading. */
|
|
134
|
+
minWidth?: number;
|
|
135
|
+
/** How willingly the column is hidden. A high column is never hidden; a low one goes first. Defaults to high. */
|
|
136
|
+
priority?: ColumnPriority;
|
|
137
|
+
}
|
|
138
|
+
/** One item of a `Tree` payload, with the items nested under it. */
|
|
139
|
+
export interface TreeNode {
|
|
140
|
+
readonly label: string;
|
|
141
|
+
/** A secondary fact, shown less prominently after the label. */
|
|
142
|
+
readonly detail?: string;
|
|
143
|
+
readonly children?: readonly TreeNode[];
|
|
144
|
+
}
|
|
145
|
+
/** {@link ReportEntryStyle.Count}. */
|
|
146
|
+
export interface CountDetails {
|
|
147
|
+
readonly count: number;
|
|
148
|
+
/** What was counted, already in the right number: `recipes`. */
|
|
149
|
+
readonly entity: string;
|
|
150
|
+
/** The verb before the count. Default `Found`; an empty string for none. */
|
|
151
|
+
readonly verb?: string;
|
|
152
|
+
}
|
|
153
|
+
/** {@link ReportEntryStyle.Problem}. */
|
|
154
|
+
export interface ProblemDetails {
|
|
155
|
+
/** What went wrong, in one sentence. */
|
|
156
|
+
readonly summary: string;
|
|
157
|
+
/** Why: the underlying error or the facts behind it. */
|
|
158
|
+
readonly cause?: string;
|
|
159
|
+
/** What to do about it. */
|
|
160
|
+
readonly hint?: string;
|
|
161
|
+
/** What it is about, such as a file or a recipe. */
|
|
162
|
+
readonly subject?: string;
|
|
163
|
+
/** For a problem in a file: the line. */
|
|
164
|
+
readonly line?: number;
|
|
165
|
+
}
|
|
166
|
+
/** {@link ReportEntryStyle.ResolvedReference}: what a reference resolved to. */
|
|
167
|
+
export interface ResolvedReferenceFacts {
|
|
168
|
+
/** What was typed. */
|
|
169
|
+
readonly search: string;
|
|
170
|
+
/** What it resolved to, in full. */
|
|
171
|
+
readonly resolvedTo: string;
|
|
172
|
+
/** What kind of thing it is: `recipe`, `namespace`, ... */
|
|
173
|
+
readonly kind: string;
|
|
174
|
+
readonly variable?: string;
|
|
175
|
+
readonly recipe?: string;
|
|
176
|
+
readonly namespace?: string;
|
|
177
|
+
readonly repository?: string;
|
|
178
|
+
readonly location?: string;
|
|
179
|
+
readonly description?: string;
|
|
180
|
+
/** Why this candidate won, in one sentence. */
|
|
181
|
+
readonly reason?: string;
|
|
182
|
+
}
|
|
183
|
+
/** {@link ReportEntryStyle.Question}. */
|
|
184
|
+
export interface QuestionDetails {
|
|
185
|
+
/** Its place in the run: question `index` of `total`. */
|
|
186
|
+
readonly index: number;
|
|
187
|
+
readonly total: number;
|
|
188
|
+
/** The variable's name. */
|
|
189
|
+
readonly name: string;
|
|
190
|
+
readonly description?: string;
|
|
191
|
+
readonly example?: string;
|
|
192
|
+
/** The recipe that asks it. */
|
|
193
|
+
readonly recipe?: string;
|
|
194
|
+
/** The file its answer goes into. */
|
|
195
|
+
readonly storedIn?: string;
|
|
196
|
+
/** The environment variable name its answer is stored as. */
|
|
197
|
+
readonly storedAs?: string;
|
|
198
|
+
}
|
|
199
|
+
/** {@link ReportEntryStyle.Command}. */
|
|
200
|
+
export interface CommandDetails {
|
|
201
|
+
readonly command: string;
|
|
202
|
+
readonly args: readonly string[];
|
|
203
|
+
/** The directory it runs in. */
|
|
204
|
+
readonly cwd?: string;
|
|
205
|
+
/** True when it would run, but a dry run does not run it. */
|
|
206
|
+
readonly dryRun?: boolean;
|
|
207
|
+
}
|
|
208
|
+
/** {@link ReportEntryStyle.Progress}: progress through a longer step, such as downloading recipes. */
|
|
209
|
+
export interface ProgressEvent {
|
|
210
|
+
/** What is in progress, in a few words: `Downloading recipes`. */
|
|
211
|
+
label: string;
|
|
212
|
+
/** How far along: items done so far. */
|
|
213
|
+
done?: number;
|
|
214
|
+
/** How far along: items in total, when known. */
|
|
215
|
+
total?: number;
|
|
216
|
+
/** The item being worked on now. */
|
|
217
|
+
item?: string;
|
|
218
|
+
/** True on the last event of this label. */
|
|
219
|
+
finished?: boolean;
|
|
220
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kinds of entry a reporter shows, and the facts each one carries in `details`. A style says what
|
|
3
|
+
* an entry IS, never how it looks: each front end's reporter decides that. A new style is added here
|
|
4
|
+
* when an output needs one, together with its convenience method in `BaseReporter` (reporter.ts),
|
|
5
|
+
* which is the only way callers produce it.
|
|
6
|
+
*
|
|
7
|
+
* Every styled message also carries a plain-text `message`, so a reporter that ignores styles (a
|
|
8
|
+
* log file, a test buffer) still has something readable.
|
|
9
|
+
*/
|
|
10
|
+
/** What kind of entry a reported message is. */
|
|
11
|
+
export const ReportEntryStyle = {
|
|
12
|
+
/** A paragraph of text, which a front end may wrap. `details` is optional data. */
|
|
13
|
+
Plain: "plain",
|
|
14
|
+
/** Text shown exactly as given: no wrapping, no color (a value printed for a script to read). No details. */
|
|
15
|
+
Text: "text",
|
|
16
|
+
/** An explanation that is neither a warning nor an error. No details. */
|
|
17
|
+
Note: "note",
|
|
18
|
+
/** The start of an operation, such as "Building the project". {@link OperationStartDetails}. */
|
|
19
|
+
OperationStart: "operation-start",
|
|
20
|
+
/** A step inside the current operation, such as one target being compiled. {@link StepStartDetails}. */
|
|
21
|
+
StepStart: "step-start",
|
|
22
|
+
/** One line of detail inside the current operation or step. No details. */
|
|
23
|
+
Detail: "detail",
|
|
24
|
+
/** One action done (or to be done) to one target, such as a file written. {@link OperationDetails}. */
|
|
25
|
+
Operation: "operation",
|
|
26
|
+
/** How an operation ended, such as "Done." {@link OperationEndDetails}. */
|
|
27
|
+
OperationEnd: "operation-end",
|
|
28
|
+
/** One label and its value. The message is a `VariableSet`. */
|
|
29
|
+
Variable: "variable",
|
|
30
|
+
/** Labels and values, read as one block, under an optional title. The message is a `VariableSet`. */
|
|
31
|
+
VariableList: "variable-list",
|
|
32
|
+
/** The facts a command runs with: the project, its config, ... The message is a `VariableSet`. */
|
|
33
|
+
CommandVariables: "command-variables",
|
|
34
|
+
/** A list of items, with an optional title and closing sentence. The message is an `ItemList`. */
|
|
35
|
+
List: "list",
|
|
36
|
+
/** A table of rows. The message is a `Table`. */
|
|
37
|
+
Table: "table",
|
|
38
|
+
/** Items nested under other items, such as each contributor and the changes it made. The message is a `Tree`. */
|
|
39
|
+
Tree: "tree",
|
|
40
|
+
/** How many things were found. {@link CountDetails}. */
|
|
41
|
+
Count: "count",
|
|
42
|
+
/** Says that a run is a dry run, or what a dry run left undone. No details. */
|
|
43
|
+
DryRun: "dry-run",
|
|
44
|
+
/** Something wrong, with its cause and what to do about it. {@link ProblemDetails}. */
|
|
45
|
+
Problem: "problem",
|
|
46
|
+
/** What a name on the command line resolved to, and why. {@link ResolvedReferenceFacts}. */
|
|
47
|
+
ResolvedReference: "resolved-reference",
|
|
48
|
+
/** The question about to be asked, and where its answer goes. {@link QuestionDetails}. */
|
|
49
|
+
Question: "question",
|
|
50
|
+
/** A command sous runs (or would run). {@link CommandDetails}. */
|
|
51
|
+
Command: "command",
|
|
52
|
+
/** Progress through a longer step. {@link ProgressEvent}. */
|
|
53
|
+
Progress: "progress",
|
|
54
|
+
/** A structured value, such as a command's result as data. The message is a `DataValue`. */
|
|
55
|
+
Data: "data",
|
|
56
|
+
/** The sous banner. No details. */
|
|
57
|
+
Banner: "banner",
|
|
58
|
+
/** A command's result: the message is `IntentOutputs`. */
|
|
59
|
+
Result: "result",
|
|
60
|
+
};
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reporting: services and intents never print. They report through the `Reporter` the front
|
|
3
|
+
* end handed over with the chain (`ctx.reporter`), and the front end decides how it looks.
|
|
4
|
+
*
|
|
5
|
+
* Every message goes through one method, `log(level, message, details?, style?)`. The level says how
|
|
6
|
+
* important it is, `details` carries its facts, and the style says what kind of entry it is (an
|
|
7
|
+
* operation, a labeled value, a table, ...). Each front end's reporter decides how each style looks:
|
|
8
|
+
* the CLI draws it with colors and alignment, MCP sends `details` as data. On top of `log` sit one
|
|
9
|
+
* method per level (`info`, `warn`, ...) and one or more methods per style (`operationStart`, ...),
|
|
10
|
+
* all defined once, in {@link BaseReporter}.
|
|
11
|
+
*/
|
|
12
|
+
import { IntentOutputs, Payload } from "./outputs.js";
|
|
13
|
+
import { type CommandDetails, type OperationAction, type OperationDetails, type ProblemDetails, type ProgressEvent, type QuestionDetails, ReportEntryStyle, type ResolvedReferenceFacts, type TableColumn, type TreeNode, type VariableEntry } from "./report-styles.js";
|
|
14
|
+
export { ReportEntryStyle } from "./report-styles.js";
|
|
15
|
+
export type * from "./report-styles.js";
|
|
16
|
+
/** The eight syslog levels, by name. */
|
|
17
|
+
export declare const LogLevel: {
|
|
18
|
+
readonly Debug: "debug";
|
|
19
|
+
readonly Info: "info";
|
|
20
|
+
readonly Notice: "notice";
|
|
21
|
+
readonly Warning: "warning";
|
|
22
|
+
readonly Error: "error";
|
|
23
|
+
readonly Critical: "critical";
|
|
24
|
+
readonly Alert: "alert";
|
|
25
|
+
readonly Emergency: "emergency";
|
|
26
|
+
};
|
|
27
|
+
/** One of the eight syslog levels. */
|
|
28
|
+
export type LogLevel = (typeof LogLevel)[keyof typeof LogLevel];
|
|
29
|
+
/** The eight syslog levels, from least to most severe. */
|
|
30
|
+
export declare const LOG_LEVELS: readonly LogLevel[];
|
|
31
|
+
/** Whether a string names a log level. */
|
|
32
|
+
export declare function isLogLevel(value: unknown): value is LogLevel;
|
|
33
|
+
/**
|
|
34
|
+
* Whether a message at `level` shows when the threshold is `threshold`.
|
|
35
|
+
*
|
|
36
|
+
* ```ts
|
|
37
|
+
* isLevelShown("warning", "notice"); // true
|
|
38
|
+
* isLevelShown("debug", "info"); // false
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function isLevelShown(level: LogLevel, threshold: LogLevel): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* What a reported message is, for people: text; an `Error`, shown with its whole cause chain; a
|
|
44
|
+
* payload (a `VariableSet`, a `Table`, ...); or, for a command's result, `IntentOutputs`.
|
|
45
|
+
*/
|
|
46
|
+
export type ReportMessage = string | Error | Payload | IntentOutputs<object>;
|
|
47
|
+
/**
|
|
48
|
+
* The text of any message: an error's chain one cause per line, a payload's or outputs' text.
|
|
49
|
+
*
|
|
50
|
+
* ```ts
|
|
51
|
+
* messageText(new Error("Could not download", { cause: new Error("DNS failed") }));
|
|
52
|
+
* // "Could not download\nCaused by: DNS failed"
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function messageText(message: ReportMessage): string;
|
|
56
|
+
/** An error and every error under it through `cause`, outermost first (a cycle stops it). */
|
|
57
|
+
export declare function errorChain(error: Error): Error[];
|
|
58
|
+
/**
|
|
59
|
+
* The facts a message carries, which a front end may show or keep (MCP sends them as data). For a
|
|
60
|
+
* styled message, its style's details type (`OperationDetails` for `ReportEntryStyle.Operation`, ...).
|
|
61
|
+
*/
|
|
62
|
+
export type ReportDetails = object;
|
|
63
|
+
/**
|
|
64
|
+
* The shared part of every reporter, and the ONE place every reporting method is defined.
|
|
65
|
+
* `Reporter`, the type plugins see, is derived from this class's public members, and the
|
|
66
|
+
* {@link Reporting} mixin copies its convenience methods onto other classes, so a method added here
|
|
67
|
+
* reaches every reporter and every class that mixes it in.
|
|
68
|
+
*
|
|
69
|
+
* A subclass writes a message that passes the threshold (`write`); everything else is shared.
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* class LinesReporter extends BaseReporter {
|
|
73
|
+
* readonly lines: string[] = [];
|
|
74
|
+
*
|
|
75
|
+
* protected write(level: LogLevel, message: string): void {
|
|
76
|
+
* this.lines.push(`${level}: ${message}`);
|
|
77
|
+
* }
|
|
78
|
+
* }
|
|
79
|
+
*
|
|
80
|
+
* const reporter = new LinesReporter(LogLevel.Warning);
|
|
81
|
+
* reporter.notice("Skipped."); // below the threshold: dropped
|
|
82
|
+
* reporter.warn("Stale."); // lines: ["warning: Stale."]
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare abstract class BaseReporter {
|
|
86
|
+
private readonly thresholdSource;
|
|
87
|
+
/**
|
|
88
|
+
* @param thresholdSource - The least severe level shown (default `debug`, everything). A function
|
|
89
|
+
* is read on every message, for a threshold that changes while the reporter is in use.
|
|
90
|
+
*/
|
|
91
|
+
constructor(thresholdSource?: LogLevel | (() => LogLevel));
|
|
92
|
+
/** The least severe level shown now. */
|
|
93
|
+
protected threshold(): LogLevel;
|
|
94
|
+
/** Whether a message at `level` passes the threshold now. */
|
|
95
|
+
protected shows(level: LogLevel): boolean;
|
|
96
|
+
/** Writes one message that passed the threshold, in the way this reporter shows `style`. */
|
|
97
|
+
protected abstract write(level: LogLevel, message: ReportMessage, details: ReportDetails | undefined, style: ReportEntryStyle): void;
|
|
98
|
+
/**
|
|
99
|
+
* Reports one message. Every other reporting method ends here.
|
|
100
|
+
*
|
|
101
|
+
* @param style - What kind of entry it is (default `ReportEntryStyle.Plain`, a paragraph).
|
|
102
|
+
*/
|
|
103
|
+
log(level: LogLevel, message: ReportMessage, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
104
|
+
/** Reports a message for whoever is debugging sous. */
|
|
105
|
+
debug(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
106
|
+
/** Reports an ordinary message. */
|
|
107
|
+
info(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
108
|
+
/** Reports a normal but significant event. */
|
|
109
|
+
notice(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
110
|
+
/** Reports something that may need the user's attention. */
|
|
111
|
+
warning(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
112
|
+
/** Shorthand for {@link warning}. */
|
|
113
|
+
warn(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
114
|
+
/** Reports something that failed. */
|
|
115
|
+
error(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
116
|
+
/** Reports a failure that stops the run. */
|
|
117
|
+
critical(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
118
|
+
/** Reports something that must be acted on at once. */
|
|
119
|
+
alert(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
120
|
+
/** Reports that sous cannot work at all. */
|
|
121
|
+
emergency(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
122
|
+
/** Shorthand for {@link emergency}. */
|
|
123
|
+
emerg(message: string | Error, details?: ReportDetails, style?: ReportEntryStyle): void;
|
|
124
|
+
/** Text shown exactly as given, such as a value a script reads: no wrapping, no color. */
|
|
125
|
+
text(content: string, level?: LogLevel): void;
|
|
126
|
+
/** An explanation that is neither a warning nor an error. */
|
|
127
|
+
note(text: string, level?: LogLevel): void;
|
|
128
|
+
/** The start of an operation: `Building the project`. */
|
|
129
|
+
operationStart(operationName: string, level?: LogLevel): void;
|
|
130
|
+
/** A step inside the current operation: one target, one recipe, one check. */
|
|
131
|
+
stepStart(stepName: string, level?: LogLevel): void;
|
|
132
|
+
/** One line of detail inside the current operation or step: `Read 12 recipes.` */
|
|
133
|
+
detail(text: string, level?: LogLevel): void;
|
|
134
|
+
/**
|
|
135
|
+
* One action done (or, in a dry run, to be done) to one target. The level defaults to `error`
|
|
136
|
+
* for `failed` and `info` for everything else.
|
|
137
|
+
*
|
|
138
|
+
* ```ts
|
|
139
|
+
* reporter.operation("written", "/work/app/CLAUDE.md", { tokens: 1840 });
|
|
140
|
+
* reporter.operation("skipped", "/work/app/AGENTS.md", { note: 'left out by the transform "strip"' });
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
operation(action: OperationAction, target: string, facts?: Omit<OperationDetails, "action" | "target">, level?: LogLevel): void;
|
|
144
|
+
/** How an operation ended: `Done.`, or `Done with 2 errors.` The level defaults to `info`, or `error` when it failed. */
|
|
145
|
+
operationEnd(summary: string, ok?: boolean, level?: LogLevel): void;
|
|
146
|
+
/** One label and its value: `Repository: /work/recipes`. */
|
|
147
|
+
variable(label: string, value: unknown, detail?: string, level?: LogLevel): void;
|
|
148
|
+
/**
|
|
149
|
+
* Labels and values, read as one block (a terminal lines their colons up). A record is read as
|
|
150
|
+
* label and value pairs, in its key order.
|
|
151
|
+
*/
|
|
152
|
+
variables(entries: readonly VariableEntry[] | Readonly<Record<string, unknown>>, title?: string, level?: LogLevel): void;
|
|
153
|
+
/** The facts a command runs with (its project, its config, what it reads), shown before its output. */
|
|
154
|
+
commandVariables(entries: readonly VariableEntry[] | Readonly<Record<string, unknown>>, level?: LogLevel): void;
|
|
155
|
+
/** A list of items, with an optional title before it and an optional sentence after it. */
|
|
156
|
+
list(items: readonly string[], options?: {
|
|
157
|
+
title?: string;
|
|
158
|
+
footer?: string;
|
|
159
|
+
}, level?: LogLevel): void;
|
|
160
|
+
/**
|
|
161
|
+
* A table of rows. With no rows, a front end shows `options.empty` when it is given;
|
|
162
|
+
* `options.rowNotes[i]` is a note shown under row `i`.
|
|
163
|
+
*/
|
|
164
|
+
table(columns: readonly TableColumn[], rows: readonly Readonly<Record<string, unknown>>[], options?: {
|
|
165
|
+
title?: string;
|
|
166
|
+
empty?: string;
|
|
167
|
+
rowNotes?: readonly (string | undefined)[];
|
|
168
|
+
}, level?: LogLevel): void;
|
|
169
|
+
/** Items nested under other items, such as each contributor and the changes it made. */
|
|
170
|
+
tree(nodes: readonly TreeNode[], title?: string, level?: LogLevel): void;
|
|
171
|
+
/** How many things were found: `Found 5 recipes`. `entity` is already in the right number. */
|
|
172
|
+
count(count: number, entity: string, verb?: string, level?: LogLevel): void;
|
|
173
|
+
/** Says that a run is a dry run, or what a dry run left undone: `Nothing was written.` */
|
|
174
|
+
dryRun(text: string, level?: LogLevel): void;
|
|
175
|
+
/**
|
|
176
|
+
* Something wrong, with its cause and what to do about it. A one-sentence warning with nothing
|
|
177
|
+
* more to say is `warn(text)` instead.
|
|
178
|
+
*
|
|
179
|
+
* ```ts
|
|
180
|
+
* reporter.problem("The compilation transform \"strip\" is not registered.", { subject: "CLAUDE.md", hint: "Install the plugin that adds it." });
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
problem(summary: string, facts?: Omit<ProblemDetails, "summary">, level?: LogLevel): void;
|
|
184
|
+
/** What a name on the command line resolved to, and why (`reason`, one sentence). */
|
|
185
|
+
resolvedReference(reason: string, facts: ResolvedReferenceFacts, level?: LogLevel): void;
|
|
186
|
+
/** The question about to be asked, and where its answer goes. */
|
|
187
|
+
question(facts: QuestionDetails, level?: LogLevel): void;
|
|
188
|
+
/** A command sous runs, or (with `dryRun`) would run. */
|
|
189
|
+
command(command: string, args: readonly string[], facts?: Omit<CommandDetails, "command" | "args">, level?: LogLevel): void;
|
|
190
|
+
/**
|
|
191
|
+
* Progress through a longer step. A terminal draws one bar and redraws it in place; the event
|
|
192
|
+
* with `finished: true` ends it.
|
|
193
|
+
*/
|
|
194
|
+
progress(event: ProgressEvent, level?: LogLevel): void;
|
|
195
|
+
/** A structured value shown as data (a config as JSON). */
|
|
196
|
+
data(value: unknown, level?: LogLevel): void;
|
|
197
|
+
/**
|
|
198
|
+
* A command's result: what its intent returned. A terminal sends it to standard output, and
|
|
199
|
+
* everything else to standard error.
|
|
200
|
+
*/
|
|
201
|
+
result(outputs: IntentOutputs<object>, level?: LogLevel): void;
|
|
202
|
+
/** The sous banner. */
|
|
203
|
+
banner(level?: LogLevel): void;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Where a chain's output goes: every public method of {@link BaseReporter}. Each front end supplies
|
|
207
|
+
* its own (the CLI writes to the terminal, MCP sends log notifications) by extending `BaseReporter`.
|
|
208
|
+
*/
|
|
209
|
+
export type Reporter = {
|
|
210
|
+
[K in keyof BaseReporter]: BaseReporter[K];
|
|
211
|
+
};
|
|
212
|
+
/** The reporting methods {@link Reporting} copies onto a class: every one except `log`. */
|
|
213
|
+
export type ReportingMethods = Omit<Reporter, "log">;
|
|
214
|
+
/** A class, abstract or not. */
|
|
215
|
+
export type AbstractConstructor<T = object> = abstract new (...args: any[]) => T;
|
|
216
|
+
/**
|
|
217
|
+
* Gives a class every reporting method of {@link BaseReporter} (`info`, `warn`, `operationStart`,
|
|
218
|
+
* ...) as a shorthand for the same method on its `reporter`, which the class provides. The methods
|
|
219
|
+
* are copied from `BaseReporter.prototype` when the mixin is applied, so nothing lists them twice.
|
|
220
|
+
* They are public, since a type can only make a member protected inside a class body.
|
|
221
|
+
*
|
|
222
|
+
* ```ts
|
|
223
|
+
* class Compiler extends Reporting(Object) {
|
|
224
|
+
* constructor(private readonly deps: { reporter: Reporter }) {
|
|
225
|
+
* super();
|
|
226
|
+
* }
|
|
227
|
+
*
|
|
228
|
+
* protected get reporter(): Reporter {
|
|
229
|
+
* return this.deps.reporter;
|
|
230
|
+
* }
|
|
231
|
+
*
|
|
232
|
+
* run(): void {
|
|
233
|
+
* this.info("Compiling"); // this.deps.reporter.info("Compiling")
|
|
234
|
+
* }
|
|
235
|
+
* }
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
export declare function Reporting<TBase extends AbstractConstructor>(Base: TBase): TBase & AbstractConstructor<ReportingMethods>;
|
|
239
|
+
/** One message a {@link BufferedReporter} kept. */
|
|
240
|
+
export interface ReportedMessage {
|
|
241
|
+
level: LogLevel;
|
|
242
|
+
message: ReportMessage;
|
|
243
|
+
details?: ReportDetails;
|
|
244
|
+
style: ReportEntryStyle;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Builds a reporter from a function that receives every message, whatever its level.
|
|
248
|
+
*
|
|
249
|
+
* ```ts
|
|
250
|
+
* const reporter = createReporter((level, message) => lines.push(`${level}: ${message}`));
|
|
251
|
+
* reporter.warn("Recipe X declares a variable no template reads.");
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
export declare function createReporter(log: (level: LogLevel, message: ReportMessage, details: ReportDetails | undefined, style: ReportEntryStyle) => void): Reporter;
|
|
255
|
+
/** A reporter that drops everything. */
|
|
256
|
+
export declare const nullReporter: Reporter;
|
|
257
|
+
/**
|
|
258
|
+
* A reporter that keeps every message, to hand on later ({@link flushTo}) or to read in tests.
|
|
259
|
+
*/
|
|
260
|
+
export declare class BufferedReporter extends BaseReporter {
|
|
261
|
+
/** Every message, in order. */
|
|
262
|
+
readonly messages: ReportedMessage[];
|
|
263
|
+
protected write(level: LogLevel, message: ReportMessage, details: ReportDetails | undefined, style: ReportEntryStyle): void;
|
|
264
|
+
/** The text of the messages at a level ({@link messageText}). */
|
|
265
|
+
at(level: LogLevel): string[];
|
|
266
|
+
/** The messages of a style. */
|
|
267
|
+
styled(style: ReportEntryStyle): ReportedMessage[];
|
|
268
|
+
/** Sends every kept message to another reporter, in order, and forgets them. */
|
|
269
|
+
flushTo(reporter: Reporter): void;
|
|
270
|
+
}
|