@ozzylabs/feedradar 0.1.9 → 0.2.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/README.ja.md +6 -3
- package/README.md +6 -3
- package/dist/agents/_boundary.d.ts +44 -0
- package/dist/agents/_boundary.d.ts.map +1 -1
- package/dist/agents/_boundary.js +80 -0
- package/dist/agents/_boundary.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +10 -3
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/routine/fire.d.ts +100 -0
- package/dist/cli/routine/fire.d.ts.map +1 -0
- package/dist/cli/routine/fire.js +196 -0
- package/dist/cli/routine/fire.js.map +1 -0
- package/dist/cli/routine/generate-pipeline.d.ts +162 -0
- package/dist/cli/routine/generate-pipeline.d.ts.map +1 -0
- package/dist/cli/routine/generate-pipeline.js +480 -0
- package/dist/cli/routine/generate-pipeline.js.map +1 -0
- package/dist/cli/routine/generate-watch.d.ts +174 -0
- package/dist/cli/routine/generate-watch.d.ts.map +1 -0
- package/dist/cli/routine/generate-watch.js +450 -0
- package/dist/cli/routine/generate-watch.js.map +1 -0
- package/dist/cli/routine.d.ts +32 -0
- package/dist/cli/routine.d.ts.map +1 -0
- package/dist/cli/routine.js +74 -0
- package/dist/cli/routine.js.map +1 -0
- package/dist/cli/triage.d.ts.map +1 -1
- package/dist/cli/triage.js +383 -78
- package/dist/cli/triage.js.map +1 -1
- package/dist/templates/agents/AGENTS.md +1 -1
- package/dist/templates/routines/pipeline.yaml.tmpl +222 -0
- package/dist/templates/routines/watch-daily.yaml +157 -0
- package/dist/templates/routines/watch.yaml.tmpl +151 -0
- package/package.json +1 -1
- package/dist/templates/routines/watch-daily.md +0 -42
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `radar routine fire <trig_id>` — trigger a Claude Routine from the outside
|
|
3
|
+
* via the `/fire` API (ADR-0020 §「外部からの起動」; epic #277 / #282).
|
|
4
|
+
*
|
|
5
|
+
* The `/fire` endpoint creates a routine session and returns immediately — it
|
|
6
|
+
* does NOT wait for the session to finish. The optional `--text` body is a
|
|
7
|
+
* free-form string passed to the session as launch context; the API does not
|
|
8
|
+
* parse it. Each routine has its own per-routine bearer token, issued ONCE in
|
|
9
|
+
* the Web UI (shown a single time; Regenerate / Revoke from there). The token
|
|
10
|
+
* is read from the environment and is NEVER printed to logs.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Base URL of the Anthropic API. Exposed as a constant (not hardcoded inline)
|
|
14
|
+
* so the fire URL stays in one place and tests can assert against it.
|
|
15
|
+
*/
|
|
16
|
+
export const ANTHROPIC_API_BASE = "https://api.anthropic.com";
|
|
17
|
+
/** Beta header gating the experimental Claude Code routines surface. */
|
|
18
|
+
export const ROUTINE_FIRE_BETA = "experimental-cc-routine-2026-04-01";
|
|
19
|
+
/** Anthropic API version pin (stable date-versioned API). */
|
|
20
|
+
export const ANTHROPIC_VERSION = "2023-06-01";
|
|
21
|
+
/** Default env var holding the per-routine `/fire` bearer token. */
|
|
22
|
+
export const DEFAULT_FIRE_TOKEN_ENV = "FEEDRADAR_ROUTINE_FIRE_TOKEN";
|
|
23
|
+
/**
|
|
24
|
+
* Routine ids issued by the Web UI carry a `trig_` prefix. We validate the
|
|
25
|
+
* shape before composing the URL so a typo'd id fails fast with a clear
|
|
26
|
+
* message instead of a 404 from the server.
|
|
27
|
+
*/
|
|
28
|
+
export function isValidRoutineId(id) {
|
|
29
|
+
return /^trig_[A-Za-z0-9._-]+$/.test(id);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* POST to `/v1/claude_code/routines/{trig_id}/fire`.
|
|
33
|
+
*
|
|
34
|
+
* The endpoint returns as soon as the session is created (it does not wait for
|
|
35
|
+
* completion). On a non-2xx status this throws with the status text; the token
|
|
36
|
+
* is never included in any error or log.
|
|
37
|
+
*/
|
|
38
|
+
export async function fireRoutine(options) {
|
|
39
|
+
const { routineId, token, text } = options;
|
|
40
|
+
const apiBase = options.apiBase ?? ANTHROPIC_API_BASE;
|
|
41
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
42
|
+
if (!isValidRoutineId(routineId)) {
|
|
43
|
+
throw new Error(`invalid routine id '${routineId}' (expected a Web UI id starting with 'trig_')`);
|
|
44
|
+
}
|
|
45
|
+
if (token.trim().length === 0) {
|
|
46
|
+
throw new Error("missing per-routine fire token");
|
|
47
|
+
}
|
|
48
|
+
const url = `${apiBase}/v1/claude_code/routines/${routineId}/fire`;
|
|
49
|
+
const headers = {
|
|
50
|
+
authorization: `Bearer ${token}`,
|
|
51
|
+
"anthropic-version": ANTHROPIC_VERSION,
|
|
52
|
+
"anthropic-beta": ROUTINE_FIRE_BETA,
|
|
53
|
+
"content-type": "application/json",
|
|
54
|
+
};
|
|
55
|
+
// The `text` body is free-form launch context; the API does not parse it.
|
|
56
|
+
// Always send a JSON object so the content-type matches even when empty.
|
|
57
|
+
const body = JSON.stringify(text === undefined ? {} : { text });
|
|
58
|
+
const response = await fetchImpl(url, { method: "POST", headers, body });
|
|
59
|
+
// Read the body once regardless of status so error and success paths share
|
|
60
|
+
// the same parse and we can surface server detail without leaking the token.
|
|
61
|
+
let parsed;
|
|
62
|
+
try {
|
|
63
|
+
parsed = await response.json();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
parsed = await response.text().catch(() => "");
|
|
67
|
+
}
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
const detail = typeof parsed === "string" && parsed.length > 0
|
|
70
|
+
? `: ${parsed}`
|
|
71
|
+
: parsed && typeof parsed === "object"
|
|
72
|
+
? `: ${JSON.stringify(parsed)}`
|
|
73
|
+
: "";
|
|
74
|
+
throw new Error(`fire failed (HTTP ${response.status} ${response.statusText})${detail}`);
|
|
75
|
+
}
|
|
76
|
+
return { status: response.status, body: parsed };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parse `routine fire <trig_id> [--text <msg>] [--token-env <NAME>]`.
|
|
80
|
+
*
|
|
81
|
+
* The routine id is a positional argument (the first non-flag token). A
|
|
82
|
+
* `--token-env` override lets a user point at a differently-named env var when
|
|
83
|
+
* juggling multiple routines, but the value is ALWAYS read from the
|
|
84
|
+
* environment — never accepted as a CLI flag (which would leak into process
|
|
85
|
+
* listings / shell history).
|
|
86
|
+
*/
|
|
87
|
+
export function parseFireRoutineArgs(args) {
|
|
88
|
+
let routineId;
|
|
89
|
+
let text;
|
|
90
|
+
let tokenEnv = DEFAULT_FIRE_TOKEN_ENV;
|
|
91
|
+
let help = false;
|
|
92
|
+
for (let i = 0; i < args.length; i++) {
|
|
93
|
+
const a = args[i];
|
|
94
|
+
if (a === "-h" || a === "--help") {
|
|
95
|
+
help = true;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (a === "--text") {
|
|
99
|
+
const value = args[++i];
|
|
100
|
+
if (value === undefined)
|
|
101
|
+
throw new Error(`option ${a} requires a value`);
|
|
102
|
+
text = value;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (a === "--token-env") {
|
|
106
|
+
const value = args[++i];
|
|
107
|
+
if (value === undefined)
|
|
108
|
+
throw new Error(`option ${a} requires a value`);
|
|
109
|
+
tokenEnv = value;
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (a === "--token") {
|
|
113
|
+
// Refuse a token on the command line: it would leak into `ps` output and
|
|
114
|
+
// shell history. Direct the user to the env-var path instead.
|
|
115
|
+
throw new Error("refusing --token on the command line (it leaks via process listing / shell history); " +
|
|
116
|
+
`set the token in the ${DEFAULT_FIRE_TOKEN_ENV} env var (or use --token-env <NAME>)`);
|
|
117
|
+
}
|
|
118
|
+
if (a?.startsWith("-")) {
|
|
119
|
+
throw new Error(`unknown option: ${a}`);
|
|
120
|
+
}
|
|
121
|
+
if (routineId !== undefined) {
|
|
122
|
+
throw new Error(`unexpected positional argument: ${a}`);
|
|
123
|
+
}
|
|
124
|
+
routineId = a;
|
|
125
|
+
}
|
|
126
|
+
return { routineId, text, tokenEnv, help };
|
|
127
|
+
}
|
|
128
|
+
export function printFireRoutineHelp(log) {
|
|
129
|
+
log("Usage: radar routine fire <trig_id> [options]");
|
|
130
|
+
log("");
|
|
131
|
+
log("Triggers a registered Claude Code Routine from the outside via the");
|
|
132
|
+
log("/fire API (ADR-0020). The call returns as soon as the routine session");
|
|
133
|
+
log("is created — it does NOT wait for the session to finish.");
|
|
134
|
+
log("");
|
|
135
|
+
log("Arguments:");
|
|
136
|
+
log(" <trig_id> Routine id from the Web UI (starts with 'trig_')");
|
|
137
|
+
log("");
|
|
138
|
+
log("Options:");
|
|
139
|
+
log(" --text <msg> Free-form launch context (request body `text`).");
|
|
140
|
+
log(" The API does not parse it; it is passed as-is.");
|
|
141
|
+
log(` --token-env <NAME> Env var holding the per-routine bearer token`);
|
|
142
|
+
log(` (default: ${DEFAULT_FIRE_TOKEN_ENV}).`);
|
|
143
|
+
log("");
|
|
144
|
+
log("The per-routine token is issued ONCE in the Web UI (Regenerate / Revoke");
|
|
145
|
+
log("there) and is read from the environment — it is never accepted as a flag");
|
|
146
|
+
log("and never printed.");
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Entry point invoked by `runRoutine` when the user types
|
|
150
|
+
* `radar routine fire`. Reads the token from the environment (never a flag,
|
|
151
|
+
* never logged) and POSTs to `/fire`.
|
|
152
|
+
*/
|
|
153
|
+
export async function runFireRoutine(args, io = {}, env = process.env, fetchImpl) {
|
|
154
|
+
const log = io.log ?? ((m) => console.log(m));
|
|
155
|
+
const error = io.error ?? ((m) => console.error(m));
|
|
156
|
+
let parsed;
|
|
157
|
+
try {
|
|
158
|
+
parsed = parseFireRoutineArgs(args);
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
error(`routine fire: ${e instanceof Error ? e.message : String(e)}`);
|
|
162
|
+
return 2;
|
|
163
|
+
}
|
|
164
|
+
if (parsed.help) {
|
|
165
|
+
printFireRoutineHelp(log);
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
if (!parsed.routineId) {
|
|
169
|
+
error("routine fire: missing <trig_id> argument (the routine id from the Web UI)");
|
|
170
|
+
printFireRoutineHelp(error);
|
|
171
|
+
return 2;
|
|
172
|
+
}
|
|
173
|
+
const token = env[parsed.tokenEnv];
|
|
174
|
+
if (!token || token.trim().length === 0) {
|
|
175
|
+
error(`routine fire: no token in ${parsed.tokenEnv}. ` +
|
|
176
|
+
`Issue a per-routine token in the Web UI and export it, e.g. ` +
|
|
177
|
+
`export ${parsed.tokenEnv}='...'`);
|
|
178
|
+
return 2;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
const result = await fireRoutine({
|
|
182
|
+
routineId: parsed.routineId,
|
|
183
|
+
token,
|
|
184
|
+
text: parsed.text,
|
|
185
|
+
fetch: fetchImpl,
|
|
186
|
+
});
|
|
187
|
+
log(`routine fire: triggered ${parsed.routineId} (HTTP ${result.status}).`);
|
|
188
|
+
log("The session was created — this call does not wait for it to finish.");
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
error(`routine fire: ${e instanceof Error ? e.message : String(e)}`);
|
|
193
|
+
return 1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=fire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fire.js","sourceRoot":"","sources":["../../../src/cli/routine/fire.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { type RoutineIO, type SupportedModel } from "./generate-watch.js";
|
|
2
|
+
/**
|
|
3
|
+
* `radar routine generate pipeline` (ADR-0020 D5 `pipeline`).
|
|
4
|
+
*
|
|
5
|
+
* Emits a Claude Routine YAML whose single session runs the FULL FeedRadar
|
|
6
|
+
* pipeline in sequence — `radar watch run` -> triage -> research -> review —
|
|
7
|
+
* processing items ONE AT A TIME via the self-session `--emit-payload` /
|
|
8
|
+
* `--commit` entrypoints (NOT `--batch`; ADR-0020 D2). The blast radius is
|
|
9
|
+
* bounded by CLI flags (`--max-items` / `--limit`), not the prompt's
|
|
10
|
+
* discretion (D3e), so a `--max-items` flag is the only structural addition
|
|
11
|
+
* over the `watch` generator.
|
|
12
|
+
*
|
|
13
|
+
* The cron / output-path / repository validators and the model roster are
|
|
14
|
+
* shared with `generate-watch.ts` rather than re-declared: routines enforce
|
|
15
|
+
* the identical 1-hour-minimum cron and `.claude/routines/*.yaml` output
|
|
16
|
+
* gate regardless of `<type>`, so a single source keeps the two in lockstep.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Default for `--max-items`: how many items one run may triage / research /
|
|
20
|
+
* review. Kept small so the routine's per-run blast radius stays bounded by a
|
|
21
|
+
* deterministic CLI cap (ADR-0020 D3e) rather than the prompt's discretion.
|
|
22
|
+
* Mirrors the conservative default of the GHA `combined-with-triage` cap.
|
|
23
|
+
*/
|
|
24
|
+
export declare const PIPELINE_DEFAULT_MAX_ITEMS = 10;
|
|
25
|
+
/**
|
|
26
|
+
* Landing / output modes for the pipeline routine's step-6 commit (#301).
|
|
27
|
+
*
|
|
28
|
+
* Symmetric with the GHA `combined-with-triage --output-mode pr|direct-commit`
|
|
29
|
+
* (#258), but the names differ because the mechanics differ:
|
|
30
|
+
*
|
|
31
|
+
* - `pr` (default): open a `claude/pipeline/...` branch + PR and STOP. A human
|
|
32
|
+
* reviews and merges. This is the ADR-0020 D3a safe default — no unreviewed
|
|
33
|
+
* routine output reaches the default branch.
|
|
34
|
+
* - `auto-merge`: open the same `claude/pipeline/...` PR, then immediately
|
|
35
|
+
* `gh pr merge --squash` it so the output lands on `main`. Distinct from the
|
|
36
|
+
* GHA `direct-commit` (which pushes to main with NO PR at all); here a PR is
|
|
37
|
+
* always created first. Opt-in because the step-5 self-review makes the PR
|
|
38
|
+
* review-complete (ADR-0020 D3a opt-in auto-merge).
|
|
39
|
+
*
|
|
40
|
+
* NB: `--auto` (vs immediate `--squash`) is intentionally NOT used — on a repo
|
|
41
|
+
* with no required checks `gh pr merge --auto` never merges, so the routine
|
|
42
|
+
* uses an immediate squash merge instead (#301).
|
|
43
|
+
*/
|
|
44
|
+
export declare const OUTPUT_MODES: readonly ["pr", "auto-merge"];
|
|
45
|
+
export type OutputMode = (typeof OUTPUT_MODES)[number];
|
|
46
|
+
/**
|
|
47
|
+
* Build the instructions step-6 commit/landing block for the given output mode.
|
|
48
|
+
*
|
|
49
|
+
* - `pr`: open a `claude/pipeline/...` branch + PR and stop (the current,
|
|
50
|
+
* pre-#301 behavior).
|
|
51
|
+
* - `auto-merge`: the same branch + PR, then `git switch main` and
|
|
52
|
+
* `gh pr merge "${BRANCH}" --squash --delete-branch` so the output lands on
|
|
53
|
+
* `main`. Switching to `main` before `--delete-branch` keeps the merge
|
|
54
|
+
* robust; the merge is fail-soft (`|| true`) so a transient failure leaves
|
|
55
|
+
* the PR open rather than aborting the routine.
|
|
56
|
+
*
|
|
57
|
+
* Emitted with the same 5-space body indentation as the surrounding numbered
|
|
58
|
+
* step (the placeholder sits where the step body starts). Exported for unit
|
|
59
|
+
* testing (mirrors the GHA generator's `buildFinalStep`).
|
|
60
|
+
*/
|
|
61
|
+
export declare function buildPipelineLandingStep(mode: OutputMode): string;
|
|
62
|
+
/**
|
|
63
|
+
* Build the hard-constraints output-gate bullet for the given output mode.
|
|
64
|
+
*
|
|
65
|
+
* - `pr`: the current "do NOT push to main; claude/* branch + PR only"
|
|
66
|
+
* constraint (ADR-0020 D3a, no auto-merge).
|
|
67
|
+
* - `auto-merge`: flips the constraint to say auto-merge is intentional — the
|
|
68
|
+
* routine opens a `claude/pipeline/...` PR then squash-merges it, and the
|
|
69
|
+
* step-5 review is what makes the PR review-complete (ADR-0020 D3a opt-in
|
|
70
|
+
* auto-merge).
|
|
71
|
+
*
|
|
72
|
+
* Exported for unit testing (mirrors the GHA generator's exported builders).
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildOutputGateConstraint(mode: OutputMode): string;
|
|
75
|
+
/**
|
|
76
|
+
* Build the `notes:` output-gate sentence for the given output mode. Mirrors
|
|
77
|
+
* `buildOutputGateConstraint` but phrased for the ops `notes` block.
|
|
78
|
+
*/
|
|
79
|
+
export declare function buildOutputGateNote(mode: OutputMode): string;
|
|
80
|
+
/**
|
|
81
|
+
* Render the bundled `pipeline.yaml.tmpl` by substituting the `{{name}}` /
|
|
82
|
+
* `{{repository}}` / `{{cron}}` / `{{timezone}}` / `{{model}}` / `{{maxItems}}`
|
|
83
|
+
* placeholders.
|
|
84
|
+
*
|
|
85
|
+
* Literal `replace` (not a templating engine): the placeholders are simple
|
|
86
|
+
* tokens and we must not expand any other `{{...}}`-looking text in the body.
|
|
87
|
+
* Exported for unit testing in isolation.
|
|
88
|
+
*/
|
|
89
|
+
export declare function renderPipelineRoutineTemplate(template: string, values: {
|
|
90
|
+
name: string;
|
|
91
|
+
repository: string;
|
|
92
|
+
cron: string;
|
|
93
|
+
timezone: string;
|
|
94
|
+
model: string;
|
|
95
|
+
maxItems: number;
|
|
96
|
+
networkAccessBlock: string;
|
|
97
|
+
landingStep: string;
|
|
98
|
+
outputGateConstraint: string;
|
|
99
|
+
outputGateNote: string;
|
|
100
|
+
allowUnrestrictedGitPush: boolean;
|
|
101
|
+
}): string;
|
|
102
|
+
export interface GeneratePipelineRoutineOptions {
|
|
103
|
+
cwd: string;
|
|
104
|
+
name: string;
|
|
105
|
+
repository: string;
|
|
106
|
+
cron: string;
|
|
107
|
+
timezone: string;
|
|
108
|
+
model: SupportedModel;
|
|
109
|
+
maxItems: number;
|
|
110
|
+
/** Landing mode for the step-6 commit (#301). Defaults to `pr`. */
|
|
111
|
+
outputMode: OutputMode;
|
|
112
|
+
output: string;
|
|
113
|
+
force: boolean;
|
|
114
|
+
/** Test seam: override the templates root location. */
|
|
115
|
+
templatesRoot?: string;
|
|
116
|
+
io?: RoutineIO;
|
|
117
|
+
}
|
|
118
|
+
export interface GeneratePipelineRoutineResult {
|
|
119
|
+
/** Relative path (from `cwd`) of the file that was written. */
|
|
120
|
+
outputPath: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Core implementation of `radar routine generate pipeline` (ADR-0020 D5
|
|
124
|
+
* `pipeline`).
|
|
125
|
+
*
|
|
126
|
+
* Validates the cron (5-field + 1-hour-minimum), output path, repository, and
|
|
127
|
+
* `--max-items` (>= 1), renders the bundled `pipeline.yaml.tmpl`, and writes it
|
|
128
|
+
* under `.claude/routines/`. The completion stdout tells the user how to paste
|
|
129
|
+
* the multi-line fields into the Web UI (yq extraction) and how to apply the
|
|
130
|
+
* schedule via `/schedule`, since Routines has no declarative apply API
|
|
131
|
+
* (ADR-0020 D1).
|
|
132
|
+
*/
|
|
133
|
+
export declare function generatePipelineRoutine(options: GeneratePipelineRoutineOptions): Promise<GeneratePipelineRoutineResult>;
|
|
134
|
+
interface ParsedFlags {
|
|
135
|
+
name: string;
|
|
136
|
+
repository: string;
|
|
137
|
+
cron: string;
|
|
138
|
+
timezone: string;
|
|
139
|
+
model: SupportedModel;
|
|
140
|
+
maxItems: number;
|
|
141
|
+
outputMode: OutputMode;
|
|
142
|
+
output: string;
|
|
143
|
+
force: boolean;
|
|
144
|
+
help: boolean;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Parse `routine generate pipeline` flags.
|
|
148
|
+
*
|
|
149
|
+
* `--output` defaults to `.claude/routines/<name>.yaml`, so it is resolved
|
|
150
|
+
* AFTER the loop once `--name` is known (a `--output` flag, if given, wins).
|
|
151
|
+
*/
|
|
152
|
+
export declare function parseGeneratePipelineRoutineArgs(args: string[]): ParsedFlags;
|
|
153
|
+
export declare function printGeneratePipelineRoutineHelp(log: (m: string) => void): void;
|
|
154
|
+
/**
|
|
155
|
+
* Entry point invoked by `runRoutine` (in `src/cli/routine.ts`) when the user
|
|
156
|
+
* types `radar routine generate pipeline`. Translates parsed flags into
|
|
157
|
+
* `generatePipelineRoutine` arguments and surfaces validation errors with the
|
|
158
|
+
* `routine generate pipeline:` prefix to match the rest of the CLI.
|
|
159
|
+
*/
|
|
160
|
+
export declare function runGeneratePipelineRoutine(args: string[], io?: RoutineIO, cwd?: string): Promise<number>;
|
|
161
|
+
export {};
|
|
162
|
+
//# sourceMappingURL=generate-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-pipeline.d.ts","sourceRoot":"","sources":["../../../src/cli/routine/generate-pipeline.ts"],"names":[],"mappings":"AAGA,OAAO,EAKL,KAAK,SAAS,EAGd,KAAK,cAAc,EACpB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;GAeG;AAEH;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,+BAAgC,CAAC;AAC1D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CA6CjE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAYlE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAc5D;AAyBD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,wBAAwB,EAAE,OAAO,CAAC;CACnC,GACA,MAAM,CAaR;AAED,MAAM,WAAW,8BAA8B;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,uDAAuD;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,EAAE,CAAC,EAAE,SAAS,CAAC;CAChB;AAED,MAAM,WAAW,6BAA6B;IAC5C,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,6BAA6B,CAAC,CAuHxC;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,cAAc,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,WAAW,CAsG5E;AAED,wBAAgB,gCAAgC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CA4B/E;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,GAAE,SAAc,EAClB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAmCjB"}
|