@fnmoa/cli 0.1.0
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.md +102 -0
- package/dist/args.js +33 -0
- package/dist/args.js.map +1 -0
- package/dist/client.js +100 -0
- package/dist/client.js.map +1 -0
- package/dist/command.js +2 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/config.js +129 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/github.js +19 -0
- package/dist/commands/github.js.map +1 -0
- package/dist/commands/oracle.js +86 -0
- package/dist/commands/oracle.js.map +1 -0
- package/dist/commands/status.js +78 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/tasks.js +156 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/commands/track.js +31 -0
- package/dist/commands/track.js.map +1 -0
- package/dist/commands/whoami.js +18 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/commands/workflows.js +304 -0
- package/dist/commands/workflows.js.map +1 -0
- package/dist/config.js +65 -0
- package/dist/config.js.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/poll.js +24 -0
- package/dist/poll.js.map +1 -0
- package/dist/registry.js +50 -0
- package/dist/registry.js.map +1 -0
- package/dist/ui.js +40 -0
- package/dist/ui.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { api } from '../client.js';
|
|
2
|
+
import { c, statusColor, relTime, die } from '../ui.js';
|
|
3
|
+
import { flagStr, flagNum, hasFlag } from '../args.js';
|
|
4
|
+
import { pollRetry, sleep } from '../poll.js';
|
|
5
|
+
const short = (t) => `${c.dim(t.id.slice(0, 8))} ${statusColor(t.status.padEnd(9))} ${c.dim(relTime(t.createdAt).padEnd(7))} ${t.prompt.replace(/\n/g, ' ').slice(0, 70)}`;
|
|
6
|
+
const fmtActivity = (e) => e.kind === 'tool' ? `${e.tool ?? 'tool'}${e.text ? `: ${e.text}` : ''}` : (e.text ?? e.kind);
|
|
7
|
+
/** Resolve a unique task-id prefix against the task list. */
|
|
8
|
+
async function resolveTaskId(idOrPrefix) {
|
|
9
|
+
const matches = (await api.tasks()).filter((t) => t.id.startsWith(idOrPrefix));
|
|
10
|
+
if (matches.length === 1)
|
|
11
|
+
return matches[0].id;
|
|
12
|
+
if (matches.length > 1)
|
|
13
|
+
die(`ambiguous task id "${idOrPrefix}" — matches ${matches.map((t) => t.id.slice(0, 8)).join(', ')}`);
|
|
14
|
+
return idOrPrefix; // no match in the list — let the server answer (404 etc.)
|
|
15
|
+
}
|
|
16
|
+
/** How long a single long-poll request blocks server-side before we re-issue. */
|
|
17
|
+
const LONGPOLL_MS = 25_000;
|
|
18
|
+
/** Await a task to completion via the server-side long-poll (`GET /tasks/:id?waitMs`):
|
|
19
|
+
* one held request per window, no activity streaming — the clean "fire then await"
|
|
20
|
+
* path (what a LangGraph tool / Worker uses). Exit 1 on failed/canceled. */
|
|
21
|
+
async function waitTask(id) {
|
|
22
|
+
for (;;) {
|
|
23
|
+
const cur = await pollRetry(() => api.task(id, LONGPOLL_MS));
|
|
24
|
+
if (['succeeded', 'failed', 'canceled'].includes(cur.status)) {
|
|
25
|
+
const cost = cur.costUsd != null ? c.dim(` $${cur.costUsd.toFixed(4)}`) : '';
|
|
26
|
+
console.log(statusColor(cur.status) + cost);
|
|
27
|
+
if (cur.result)
|
|
28
|
+
console.log('\n' + cur.result);
|
|
29
|
+
if (cur.error)
|
|
30
|
+
console.log(c.red('\n' + cur.error));
|
|
31
|
+
if (cur.status !== 'succeeded')
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Still running after the window — re-issue. Small floor sleep so this can't
|
|
36
|
+
// hot-loop against a server that ignores `waitMs` (returns immediately); it's
|
|
37
|
+
// negligible once the server honors the long-poll.
|
|
38
|
+
await sleep(1000);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Poll a task to completion, streaming new activity events as they arrive.
|
|
42
|
+
* Sets exit code 1 if the task ends failed/canceled. */
|
|
43
|
+
async function watchTask(id) {
|
|
44
|
+
let seen = 0;
|
|
45
|
+
for (;;) {
|
|
46
|
+
const cur = await pollRetry(() => api.task(id));
|
|
47
|
+
const acts = cur.activity ?? [];
|
|
48
|
+
if (seen > acts.length)
|
|
49
|
+
seen = acts.length; // server caps the feed; resync
|
|
50
|
+
for (const e of acts.slice(seen))
|
|
51
|
+
console.log(`${c.dim('·')} ${fmtActivity(e)}`);
|
|
52
|
+
seen = acts.length;
|
|
53
|
+
if (['succeeded', 'failed', 'canceled'].includes(cur.status)) {
|
|
54
|
+
console.log(statusColor(cur.status));
|
|
55
|
+
if (cur.result)
|
|
56
|
+
console.log('\n' + cur.result);
|
|
57
|
+
if (cur.error)
|
|
58
|
+
console.log(c.red('\n' + cur.error));
|
|
59
|
+
if (cur.status !== 'succeeded')
|
|
60
|
+
process.exitCode = 1;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
await sleep(2500);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export const tasksCmd = {
|
|
67
|
+
name: 'tasks',
|
|
68
|
+
group: 'tasks',
|
|
69
|
+
summary: 'List tasks (newest first).',
|
|
70
|
+
usage: 'moa tasks [--limit N] [--json]',
|
|
71
|
+
args: [
|
|
72
|
+
{ name: '--limit', desc: 'max tasks to show (default 30)' },
|
|
73
|
+
{ name: '--json', desc: 'print the raw API response as JSON' },
|
|
74
|
+
],
|
|
75
|
+
async run(a) {
|
|
76
|
+
const limit = flagNum(a, 'limit') ?? 30;
|
|
77
|
+
const ts = (await api.tasks(limit)).slice(0, limit);
|
|
78
|
+
if (hasFlag(a, 'json'))
|
|
79
|
+
return console.log(JSON.stringify(ts, null, 2));
|
|
80
|
+
if (!ts.length)
|
|
81
|
+
return console.log(c.dim('no tasks'));
|
|
82
|
+
ts.forEach((t) => console.log(short(t)));
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
export const taskCmd = {
|
|
86
|
+
name: 'task',
|
|
87
|
+
group: 'tasks',
|
|
88
|
+
summary: 'Show one task with its full result (id prefixes ok).',
|
|
89
|
+
usage: 'moa task <id> [--watch] [--wait] [--json]',
|
|
90
|
+
args: [
|
|
91
|
+
{ name: 'id', required: true, desc: 'task id (a unique prefix works)' },
|
|
92
|
+
{ name: '--watch', desc: 'stream activity until the task finishes' },
|
|
93
|
+
{ name: '--wait', desc: 'block (server-side long-poll) until the task settles, then print the result' },
|
|
94
|
+
{ name: '--json', desc: 'print the raw API response as JSON' },
|
|
95
|
+
],
|
|
96
|
+
async run(a) {
|
|
97
|
+
const arg = a.pos[0] ?? die('usage: moa task <id> [--watch] [--wait] [--json]');
|
|
98
|
+
const id = await resolveTaskId(arg);
|
|
99
|
+
if (hasFlag(a, 'watch'))
|
|
100
|
+
return watchTask(id);
|
|
101
|
+
if (hasFlag(a, 'wait'))
|
|
102
|
+
return waitTask(id);
|
|
103
|
+
const t = await api.task(id);
|
|
104
|
+
if (hasFlag(a, 'json'))
|
|
105
|
+
return console.log(JSON.stringify(t, null, 2));
|
|
106
|
+
console.log(`${c.bold('task')} ${c.dim(t.id)} ${statusColor(t.status)}${t.costUsd != null ? ' ' + c.dim('$' + t.costUsd.toFixed(4)) : ''}`);
|
|
107
|
+
console.log(c.dim('dir ') + t.dir);
|
|
108
|
+
console.log(c.bold('\nprompt:') + '\n' + t.prompt);
|
|
109
|
+
if (t.result)
|
|
110
|
+
console.log(c.bold('\nresult:') + '\n' + t.result);
|
|
111
|
+
if (t.error)
|
|
112
|
+
console.log(c.red('\nerror:') + '\n' + t.error);
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
export const runCmd = {
|
|
116
|
+
name: 'run',
|
|
117
|
+
group: 'tasks',
|
|
118
|
+
summary: 'Enqueue a coding task for the agent.',
|
|
119
|
+
usage: 'moa run "<prompt>" [--dir D] [--mode M] [--watch | --wait]',
|
|
120
|
+
args: [
|
|
121
|
+
{ name: 'prompt', required: true, desc: 'the instruction for the agent' },
|
|
122
|
+
{ name: '--dir', desc: 'working directory (defaults to the server workspace)' },
|
|
123
|
+
{ name: '--mode', desc: 'agent pipeline mode: scout (default) | oracle | architect | striker' },
|
|
124
|
+
{ name: '--watch', desc: 'stream activity until the task finishes' },
|
|
125
|
+
{ name: '--wait', desc: 'block (server-side long-poll) until the task settles, then print the result' },
|
|
126
|
+
],
|
|
127
|
+
examples: [
|
|
128
|
+
'moa run "add a hello() to src/index.ts" --watch',
|
|
129
|
+
'moa run "bump version to 1.2.0" --mode striker --wait',
|
|
130
|
+
],
|
|
131
|
+
async run(a) {
|
|
132
|
+
const prompt = a.pos.join(' ') || die('usage: moa run "<prompt>" [--dir D] [--mode M]');
|
|
133
|
+
const mode = flagStr(a, 'mode');
|
|
134
|
+
if (mode && !['scout', 'oracle', 'architect', 'striker'].includes(mode)) {
|
|
135
|
+
die('--mode must be one of: scout, oracle, architect, striker');
|
|
136
|
+
}
|
|
137
|
+
const t = await api.run({ task: prompt, dir: flagStr(a, 'dir'), mode });
|
|
138
|
+
console.log(c.green(`queued task ${t.id}`));
|
|
139
|
+
if (hasFlag(a, 'wait'))
|
|
140
|
+
await waitTask(t.id);
|
|
141
|
+
else if (hasFlag(a, 'watch'))
|
|
142
|
+
await watchTask(t.id);
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
export const cancelCmd = {
|
|
146
|
+
name: 'cancel',
|
|
147
|
+
group: 'tasks',
|
|
148
|
+
summary: 'Cancel a running task.',
|
|
149
|
+
usage: 'moa cancel <taskId>',
|
|
150
|
+
args: [{ name: 'taskId', required: true, desc: 'task id' }],
|
|
151
|
+
async run(a) {
|
|
152
|
+
const id = a.pos[0] ?? die('usage: moa cancel <taskId>');
|
|
153
|
+
console.log(statusColor((await api.cancelTask(id)).status));
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/commands/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { api } from '../client.js';
|
|
2
|
+
import { c, relTime } from '../ui.js';
|
|
3
|
+
import { hasFlag } from '../args.js';
|
|
4
|
+
/** The issue pipeline: each tracked issue and the stage it's reached. */
|
|
5
|
+
export const trackCmd = {
|
|
6
|
+
name: 'track',
|
|
7
|
+
group: 'workflows',
|
|
8
|
+
summary: 'Issue pipeline — each tracked issue and its lifecycle stage.',
|
|
9
|
+
usage: 'moa track [repo] [--json]',
|
|
10
|
+
args: [
|
|
11
|
+
{ name: 'repo', desc: 'filter to owner/repo' },
|
|
12
|
+
{ name: '--json', desc: 'print the raw API response as JSON' },
|
|
13
|
+
],
|
|
14
|
+
examples: ['moa track', 'moa track fnLog0/moa-tests'],
|
|
15
|
+
async run(a) {
|
|
16
|
+
const repo = a.pos[0];
|
|
17
|
+
let tracks = await api.tracks();
|
|
18
|
+
if (repo)
|
|
19
|
+
tracks = tracks.filter((t) => t.repo === repo);
|
|
20
|
+
if (hasFlag(a, 'json'))
|
|
21
|
+
return console.log(JSON.stringify(tracks, null, 2));
|
|
22
|
+
if (!tracks.length)
|
|
23
|
+
return console.log(c.dim('no tracked issues'));
|
|
24
|
+
for (const t of tracks) {
|
|
25
|
+
const pr = t.prNumber ? c.cyan(`PR #${t.prNumber}`) : c.dim('no PR');
|
|
26
|
+
const rr = t.reviewRequested ? ' ' + c.amber('review requested') : '';
|
|
27
|
+
console.log(`${c.dim(relTime(t.updatedAt ?? '').padEnd(7))} ${`${t.repo}#${t.issueNumber}`.padEnd(24)} ${c.amber(t.stage.padEnd(18))} ${pr}${rr} ${c.dim(t.title ?? '')}`);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=track.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track.js","sourceRoot":"","sources":["../../src/commands/track.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,OAAO,EAAa,MAAM,YAAY,CAAC;AAGhD,yEAAyE;AACzE,MAAM,CAAC,MAAM,QAAQ,GAAY;IAC/B,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,WAAW;IAClB,OAAO,EAAE,8DAA8D;IACvE,KAAK,EAAE,2BAA2B;IAClC,IAAI,EAAE;QACJ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE;QAC9C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,oCAAoC,EAAE;KAC/D;IACD,QAAQ,EAAE,CAAC,WAAW,EAAE,4BAA4B,CAAC;IACrD,KAAK,CAAC,GAAG,CAAC,CAAO;QACf,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;QAChC,IAAI,IAAI;YAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACzD,IAAI,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5E,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACnE,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM,EAAE,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACvE,OAAO,CAAC,GAAG,CACT,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAC/J,CAAC;QACJ,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { api, API_URL, PROFILE } from '../client.js';
|
|
2
|
+
import { c } from '../ui.js';
|
|
3
|
+
/** Who am I right now — the active profile and the operator it acts as. */
|
|
4
|
+
export const whoamiCmd = {
|
|
5
|
+
name: 'whoami',
|
|
6
|
+
group: 'status',
|
|
7
|
+
summary: 'Show the active profile + the operator (GitHub login) it acts as.',
|
|
8
|
+
usage: 'moa whoami',
|
|
9
|
+
examples: ['moa whoami', 'MOA_PROFILE=fnlog0 moa whoami'],
|
|
10
|
+
async run() {
|
|
11
|
+
const s = (await api.setup());
|
|
12
|
+
console.log(`profile : ${c.green(PROFILE)}`);
|
|
13
|
+
console.log(`url : ${API_URL}`);
|
|
14
|
+
console.log(`operator : ${s.github?.login ? c.cyan('@' + s.github.login) : c.dim('(github not connected)')}`);
|
|
15
|
+
console.log(`claude : ${s.claude?.connected ? c.green('connected') : c.dim('not connected')}`);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=whoami.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,CAAC,EAAE,MAAM,UAAU,CAAC;AAG7B,2EAA2E;AAC3E,MAAM,CAAC,MAAM,SAAS,GAAY;IAChC,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,mEAAmE;IAC5E,KAAK,EAAE,YAAY;IACnB,QAAQ,EAAE,CAAC,YAAY,EAAE,+BAA+B,CAAC;IACzD,KAAK,CAAC,GAAG;QACP,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAG3B,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,EAAE,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC;QAC9G,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACnG,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { api } from '../client.js';
|
|
2
|
+
import { c, statusColor, relTime, die } from '../ui.js';
|
|
3
|
+
import { flagStr, flagNum, hasFlag } from '../args.js';
|
|
4
|
+
import { pollRetry, sleep } from '../poll.js';
|
|
5
|
+
/** Trigger sub-actions: action → endpoint + which number field it takes. */
|
|
6
|
+
const TRIGGERS = {
|
|
7
|
+
solve: { path: 'issue-to-pr', numKey: 'issueNumber', noun: 'issue#', summary: 'Implement an issue → open a PR.' },
|
|
8
|
+
branch: { path: 'issue-to-branch', numKey: 'issueNumber', noun: 'issue#', summary: 'Solve an issue → push to a branch (no PR; re-runnable).' },
|
|
9
|
+
'open-pr': { path: 'open-pr', numKey: 'issueNumber', noun: 'issue#', summary: "Open (or reuse) a PR from an issue's branch (no agent)." },
|
|
10
|
+
triage: { path: 'triage', numKey: 'issueNumber', noun: 'issue#', summary: 'Categorize + label an issue.' },
|
|
11
|
+
review: { path: 'review-pr', numKey: 'prNumber', noun: 'pr#', summary: 'Review a PR (inline comments + verdict).' },
|
|
12
|
+
'review-fix': { path: 'review-fix', numKey: 'prNumber', noun: 'pr#', summary: 'Review a PR → fix the findings → re-verify → approve when clean.' },
|
|
13
|
+
address: { path: 'address-comments', numKey: 'prNumber', noun: 'pr#', summary: "Push fixes for a PR's review feedback." },
|
|
14
|
+
'fix-ci': { path: 'fix-ci', numKey: 'prNumber', noun: 'pr#', summary: 'Diagnose + fix failing CI on a PR.' },
|
|
15
|
+
merge: { path: 'auto-merge', numKey: 'prNumber', noun: 'pr#', summary: 'Merge a PR if approved + CI green. --wait parks until pending CI finishes, then merges.' },
|
|
16
|
+
};
|
|
17
|
+
const isTerminal = (s) => s === 'succeeded' || s === 'failed' || s === 'canceled';
|
|
18
|
+
const isParked = (s) => s === 'awaiting_approval';
|
|
19
|
+
/** Resolve a unique workflow run-id prefix against the run list. */
|
|
20
|
+
async function resolveWorkflowId(idOrPrefix) {
|
|
21
|
+
const { runs } = await api.workflows();
|
|
22
|
+
const matches = runs.filter((r) => r.id.startsWith(idOrPrefix));
|
|
23
|
+
if (matches.length === 1)
|
|
24
|
+
return matches[0].id;
|
|
25
|
+
if (matches.length > 1)
|
|
26
|
+
die(`ambiguous workflow id "${idOrPrefix}" — matches ${matches.map((r) => r.id.slice(0, 8)).join(', ')}`);
|
|
27
|
+
return idOrPrefix; // no match in the list — let the server answer (404 etc.)
|
|
28
|
+
}
|
|
29
|
+
function printRun(r) {
|
|
30
|
+
console.log(`${c.bold(r.type)} ${c.dim(r.repo + '#' + r.sourceNumber)} ${statusColor(r.status)}${r.verdict && r.verdict !== 'comment' ? ' ' + c.amber(r.verdict) : ''}${r.costUsd != null ? ' ' + c.dim('$' + r.costUsd.toFixed(4)) : ''}`);
|
|
31
|
+
if (r.prUrl)
|
|
32
|
+
console.log(` ${c.cyan(r.prUrl)}`);
|
|
33
|
+
else if (r.branch)
|
|
34
|
+
console.log(` ${c.dim('branch')} ${r.branch}`);
|
|
35
|
+
if (r.error)
|
|
36
|
+
console.log(` ${c.red(r.error)}`);
|
|
37
|
+
if (r.steps?.length)
|
|
38
|
+
console.log(' ' + c.dim(r.steps.join(' → ')));
|
|
39
|
+
if ((r.status === 'running' || r.status === 'queued') && r.updatedAt) {
|
|
40
|
+
const parts = [`active ${relTime(r.updatedAt)}`];
|
|
41
|
+
if (r.steps?.length)
|
|
42
|
+
parts.push(`${r.steps.length} step${r.steps.length === 1 ? '' : 's'}`);
|
|
43
|
+
console.log(` ${c.dim(parts.join(' · '))}`);
|
|
44
|
+
}
|
|
45
|
+
if (r.status === 'awaiting_approval') {
|
|
46
|
+
if (r.plan) {
|
|
47
|
+
console.log('');
|
|
48
|
+
console.log(r.plan);
|
|
49
|
+
console.log('');
|
|
50
|
+
}
|
|
51
|
+
const id = r.id.slice(0, 8);
|
|
52
|
+
console.log(c.amber(` → approve: moa wf approve ${id} [--instruction "…"]`));
|
|
53
|
+
console.log(c.dim(` → discard: moa wf cancel ${id}`));
|
|
54
|
+
}
|
|
55
|
+
if (r.type === 'review-pr' && r.status === 'succeeded' && r.verdict && r.verdict !== 'APPROVE') {
|
|
56
|
+
console.log(` ${c.dim(`→ run \`wf review-fix ${r.repo} ${r.sourceNumber}\` to fix findings and get approval`)}`);
|
|
57
|
+
}
|
|
58
|
+
if ((r.type === 'issue-to-pr' || r.type === 'issue-to-branch') && r.status === 'failed') {
|
|
59
|
+
console.log(` ${c.dim(`→ re-run with \`--instruction "…"\` to scope the agent (e.g. "focus on X, skip Y")`)}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function watchRun(id) {
|
|
63
|
+
let last = '';
|
|
64
|
+
for (;;) {
|
|
65
|
+
const r = await pollRetry(() => api.workflow(id));
|
|
66
|
+
const step = r.steps?.[r.steps.length - 1] ?? r.status;
|
|
67
|
+
if (step !== last) {
|
|
68
|
+
console.log(`${c.dim('·')} ${step}`);
|
|
69
|
+
last = step;
|
|
70
|
+
}
|
|
71
|
+
if (isTerminal(r.status)) {
|
|
72
|
+
if (r.status !== 'succeeded')
|
|
73
|
+
process.exitCode = 1;
|
|
74
|
+
return printRun(r);
|
|
75
|
+
}
|
|
76
|
+
if (isParked(r.status)) {
|
|
77
|
+
return printRun(r);
|
|
78
|
+
}
|
|
79
|
+
await sleep(2500);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function waitBatch(ids) {
|
|
83
|
+
const resolved = await Promise.all(ids.map(resolveWorkflowId));
|
|
84
|
+
await Promise.all(resolved.map(async (id) => {
|
|
85
|
+
for (;;) {
|
|
86
|
+
const r = await pollRetry(() => api.workflow(id));
|
|
87
|
+
if (isTerminal(r.status)) {
|
|
88
|
+
if (r.status !== 'succeeded')
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
printRun(r);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await sleep(2500);
|
|
94
|
+
}
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
/** Which actions accept --base (branch off a non-default base) and --restart (fresh branch). */
|
|
98
|
+
const takesBase = (name) => name === 'solve' || name === 'branch' || name === 'open-pr';
|
|
99
|
+
const takesRestart = (name) => name === 'solve' || name === 'branch';
|
|
100
|
+
const takesInstruction = (name) => name === 'solve' || name === 'branch';
|
|
101
|
+
const takesGate = (name) => name === 'solve' || name === 'fix-ci';
|
|
102
|
+
const takesLabel = (name) => name === 'solve';
|
|
103
|
+
// Sub-action catalog entries (for help + the AI knowledge base).
|
|
104
|
+
const triggerMeta = Object.entries(TRIGGERS).map(([name, t]) => ({
|
|
105
|
+
name: `wf ${name}`,
|
|
106
|
+
group: 'workflows',
|
|
107
|
+
summary: t.summary,
|
|
108
|
+
usage: `moa wf ${name} <repo> <${t.noun}>${t.numKey === 'issueNumber' ? `[,${t.noun},…]` : ''}${takesLabel(name) ? ' [--label <label>]' : ''}${takesBase(name) ? ' [--base B]' : ''}${takesInstruction(name) ? ' [--instruction "…"]' : ''}${takesRestart(name) ? ' [--restart]' : ''}${takesGate(name) ? ' [--gate]' : ''} [--watch]`,
|
|
109
|
+
args: [
|
|
110
|
+
{ name: 'repo', required: true, desc: 'owner/repo' },
|
|
111
|
+
{ name: t.noun, required: t.numKey !== 'issueNumber' || !takesLabel(name), desc: t.numKey === 'issueNumber' ? 'issue number(s), comma-separated' : 'PR number' },
|
|
112
|
+
...(takesLabel(name) ? [{ name: '--label', desc: 'queue a run for every open issue in the repo carrying this label' }] : []),
|
|
113
|
+
...(takesBase(name) ? [{ name: '--base', desc: 'base branch (default: repo default)' }] : []),
|
|
114
|
+
...(takesInstruction(name) ? [{ name: '--instruction', desc: 'extra instruction for this run — use this to scope a big or ambiguous issue' }] : []),
|
|
115
|
+
...(takesRestart(name) ? [{ name: '--restart', desc: 'reset the branch off base instead of continuing it' }] : []),
|
|
116
|
+
...(takesGate(name) ? [{ name: '--gate', desc: 'plan first, park for approval, then execute (avoids committing to a costly run sight-unseen)' }] : []),
|
|
117
|
+
{ name: '--watch', desc: 'stream the step timeline until done' },
|
|
118
|
+
],
|
|
119
|
+
examples: [
|
|
120
|
+
`moa wf ${name} acme/app ${t.numKey === 'issueNumber' ? '42' : '7'} --watch`,
|
|
121
|
+
...(takesLabel(name) ? ['moa wf solve acme/app --label wave:1', 'moa wf solve acme/app 2,3,4,5'] : []),
|
|
122
|
+
...(takesGate(name) ? [`moa wf ${name} acme/app ${t.numKey === 'issueNumber' ? '42' : '7'} --gate --watch`] : []),
|
|
123
|
+
],
|
|
124
|
+
}));
|
|
125
|
+
export const wfCmd = {
|
|
126
|
+
name: 'wf',
|
|
127
|
+
group: 'workflows',
|
|
128
|
+
summary: 'Workflow runs: list, inspect, and trigger.',
|
|
129
|
+
usage: 'moa wf [list|pending|get <id>|cancel <id>|approve <id>|<action> <repo> <num>]',
|
|
130
|
+
subcommands: [
|
|
131
|
+
{
|
|
132
|
+
name: 'wf',
|
|
133
|
+
group: 'workflows',
|
|
134
|
+
summary: 'List workflow runs.',
|
|
135
|
+
usage: 'moa wf [list] [--limit N] [--json]',
|
|
136
|
+
args: [
|
|
137
|
+
{ name: '--limit', desc: 'max runs to show (default 30)' },
|
|
138
|
+
{ name: '--json', desc: 'print the raw API response as JSON' },
|
|
139
|
+
],
|
|
140
|
+
examples: ['moa wf', 'moa wf list --limit 10 --json'],
|
|
141
|
+
},
|
|
142
|
+
{ name: 'wf pending', group: 'workflows', summary: 'Open issues/PRs available to act on.', usage: 'moa wf pending', examples: ['moa wf pending'] },
|
|
143
|
+
{
|
|
144
|
+
name: 'wf get',
|
|
145
|
+
group: 'workflows',
|
|
146
|
+
summary: 'Show one run + step timeline.',
|
|
147
|
+
usage: 'moa wf get <id> [--watch] [--json]',
|
|
148
|
+
args: [
|
|
149
|
+
{ name: 'id', required: true, desc: 'run id' },
|
|
150
|
+
{ name: '--watch', desc: 'stream the step timeline until done' },
|
|
151
|
+
{ name: '--json', desc: 'print the raw API response as JSON' },
|
|
152
|
+
],
|
|
153
|
+
examples: ['moa wf get a1b2c3d4 --watch'],
|
|
154
|
+
},
|
|
155
|
+
{ name: 'wf cancel', group: 'workflows', summary: 'Cancel a run.', usage: 'moa wf cancel <id>', examples: ['moa wf cancel a1b2c3d4'] },
|
|
156
|
+
{
|
|
157
|
+
name: 'wf approve',
|
|
158
|
+
group: 'workflows',
|
|
159
|
+
summary: 'Approve a gated run (awaiting_approval) — resumes execute.',
|
|
160
|
+
usage: 'moa wf approve <id> [--instruction "…"]',
|
|
161
|
+
args: [
|
|
162
|
+
{ name: 'id', required: true, desc: 'run id' },
|
|
163
|
+
{ name: '--instruction', desc: 'optional steering for the execute phase' },
|
|
164
|
+
],
|
|
165
|
+
examples: ['moa wf approve a1b2c3d4', 'moa wf approve a1b2c3d4 --instruction "focus on the auth module only"'],
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'wf wait',
|
|
169
|
+
group: 'workflows',
|
|
170
|
+
summary: 'Block until a batch of runs finishes; exit non-zero if any failed.',
|
|
171
|
+
usage: 'moa wf wait <id>[,id,…]',
|
|
172
|
+
args: [{ name: 'id', required: true, desc: 'run id(s), space- or comma-separated' }],
|
|
173
|
+
examples: ['moa wf wait a1b2c3d4 e5f6a7b8', 'moa wf wait a1b2,e5f6'],
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'wf report-issue',
|
|
177
|
+
group: 'workflows',
|
|
178
|
+
summary: 'Audit a repo → file one or more issues (the agent decides).',
|
|
179
|
+
usage: 'moa wf report-issue <repo> [--instruction "…"] [--watch]',
|
|
180
|
+
args: [
|
|
181
|
+
{ name: 'repo', required: true, desc: 'owner/repo' },
|
|
182
|
+
{ name: '--instruction', desc: 'what to look for / report (e.g. "audit error handling")' },
|
|
183
|
+
{ name: '--watch', desc: 'stream the step timeline until done' },
|
|
184
|
+
],
|
|
185
|
+
examples: ['moa wf report-issue acme/app --instruction "find missing tests" --watch'],
|
|
186
|
+
},
|
|
187
|
+
...triggerMeta,
|
|
188
|
+
],
|
|
189
|
+
async run(a) {
|
|
190
|
+
const sub = a.pos[0];
|
|
191
|
+
if (!sub || sub === 'list') {
|
|
192
|
+
const limit = flagNum(a, 'limit') ?? 30;
|
|
193
|
+
const { runs: allRuns, queue } = await api.workflows(limit);
|
|
194
|
+
const runs = allRuns.slice(0, limit);
|
|
195
|
+
if (hasFlag(a, 'json'))
|
|
196
|
+
return console.log(JSON.stringify({ runs, queue }, null, 2));
|
|
197
|
+
if (queue.running > 0 || queue.queued > 0)
|
|
198
|
+
console.log(c.dim(`running ${queue.running}/${queue.limit} · queued ${queue.queued}`));
|
|
199
|
+
if (!runs.length)
|
|
200
|
+
return console.log(c.dim('no runs'));
|
|
201
|
+
runs.forEach((r) => console.log(`${c.dim(r.id.slice(0, 8))} ${statusColor(r.status.padEnd(9))} ${c.dim(relTime(r.createdAt).padEnd(7))} ${c.bold(r.type.padEnd(15))} ${r.repo}#${r.sourceNumber}`));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (sub === 'pending') {
|
|
205
|
+
const p = await api.pending();
|
|
206
|
+
if (!p.connected)
|
|
207
|
+
return console.log(c.red('GitHub not connected'));
|
|
208
|
+
if (!p.items.length)
|
|
209
|
+
return console.log(c.dim('nothing pending ✓'));
|
|
210
|
+
p.items.forEach((it) => {
|
|
211
|
+
console.log(`${it.kind === 'issue' ? c.green('issue') : c.cyan('pull ')} ${it.repo}#${it.number} ${c.dim(it.title)}`);
|
|
212
|
+
it.conflictWarnings?.forEach((w) => console.log(` ${c.amber(w)}`));
|
|
213
|
+
});
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (sub === 'get') {
|
|
217
|
+
const raw = a.pos[1] ?? die('usage: moa wf get <id> [--watch] [--json]');
|
|
218
|
+
const id = await resolveWorkflowId(raw);
|
|
219
|
+
if (hasFlag(a, 'watch'))
|
|
220
|
+
return watchRun(id);
|
|
221
|
+
const r = await api.workflow(id);
|
|
222
|
+
return hasFlag(a, 'json') ? console.log(JSON.stringify(r, null, 2)) : printRun(r);
|
|
223
|
+
}
|
|
224
|
+
if (sub === 'cancel') {
|
|
225
|
+
const raw = a.pos[1] ?? die('usage: moa wf cancel <id>');
|
|
226
|
+
const id = await resolveWorkflowId(raw);
|
|
227
|
+
return printRun(await api.cancelWorkflow(id));
|
|
228
|
+
}
|
|
229
|
+
if (sub === 'approve') {
|
|
230
|
+
const raw = a.pos[1] ?? die('usage: moa wf approve <id> [--instruction "…"]');
|
|
231
|
+
const id = await resolveWorkflowId(raw);
|
|
232
|
+
const instruction = flagStr(a, 'instruction');
|
|
233
|
+
return printRun(await api.approveWorkflow(id, instruction ? { instruction } : undefined));
|
|
234
|
+
}
|
|
235
|
+
if (sub === 'wait') {
|
|
236
|
+
const rawIds = a.pos.slice(1);
|
|
237
|
+
if (!rawIds.length)
|
|
238
|
+
die('usage: moa wf wait <id>[,id,…]');
|
|
239
|
+
const ids = rawIds.flatMap((s) => s.split(',').map((x) => x.trim())).filter(Boolean);
|
|
240
|
+
return waitBatch(ids);
|
|
241
|
+
}
|
|
242
|
+
// report-issue is repo-only (no issue/PR number) — the agent decides what to file.
|
|
243
|
+
if (sub === 'report-issue') {
|
|
244
|
+
const repo = a.pos[1] ?? die('usage: moa wf report-issue <owner/repo> [--instruction "…"]');
|
|
245
|
+
if (!repo.includes('/'))
|
|
246
|
+
die('usage: moa wf report-issue <owner/repo> [--instruction "…"]');
|
|
247
|
+
const body = { repo };
|
|
248
|
+
const instruction = flagStr(a, 'instruction');
|
|
249
|
+
if (instruction)
|
|
250
|
+
body.instruction = instruction;
|
|
251
|
+
const run = await api.trigger('report-issue', body);
|
|
252
|
+
console.log(c.green(`started report-issue → ${run.id.slice(0, 8)}`));
|
|
253
|
+
if (hasFlag(a, 'watch'))
|
|
254
|
+
await watchRun(run.id);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const trig = TRIGGERS[sub];
|
|
258
|
+
if (!trig)
|
|
259
|
+
die(`unknown workflow command: ${sub}`);
|
|
260
|
+
const repo = a.pos[1] ?? die(`usage: moa wf ${sub} <owner/repo> <${trig.noun}>`);
|
|
261
|
+
if (!repo.includes('/'))
|
|
262
|
+
die(`usage: moa wf ${sub} <owner/repo> <${trig.noun}>`);
|
|
263
|
+
// Resolve the set of issue/PR numbers to act on.
|
|
264
|
+
let nums;
|
|
265
|
+
const label = takesLabel(sub) ? flagStr(a, 'label') : undefined;
|
|
266
|
+
if (label) {
|
|
267
|
+
const list = await api.ghIssuesByLabel(repo, label);
|
|
268
|
+
if (!list.connected)
|
|
269
|
+
die('GitHub not connected — run `moa config set token <token>`');
|
|
270
|
+
nums = list.items.map((it) => it.number);
|
|
271
|
+
if (!nums.length)
|
|
272
|
+
die(`no open issues with label "${label}" in ${repo}`);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const raw = a.pos[2] ?? die(`usage: moa wf ${sub} <owner/repo> <${trig.noun}>`);
|
|
276
|
+
nums = raw.split(',').map((s) => Number(s.trim())).filter((n) => Number.isFinite(n) && n > 0);
|
|
277
|
+
if (!nums.length)
|
|
278
|
+
die(`usage: moa wf ${sub} <owner/repo> <${trig.noun}>`);
|
|
279
|
+
}
|
|
280
|
+
const base = flagStr(a, 'base');
|
|
281
|
+
const instruction = flagStr(a, 'instruction');
|
|
282
|
+
const watch = hasFlag(a, 'watch');
|
|
283
|
+
const multi = nums.length > 1;
|
|
284
|
+
for (const num of nums) {
|
|
285
|
+
const body = { repo, [trig.numKey]: num };
|
|
286
|
+
if (takesBase(sub) && base)
|
|
287
|
+
body.baseBranch = base;
|
|
288
|
+
if (takesInstruction(sub) && instruction)
|
|
289
|
+
body.instruction = instruction;
|
|
290
|
+
if (takesRestart(sub) && hasFlag(a, 'restart'))
|
|
291
|
+
body.restart = true;
|
|
292
|
+
if (takesGate(sub) && hasFlag(a, 'gate'))
|
|
293
|
+
body.gate = true;
|
|
294
|
+
// merge --wait: park until pending CI finishes, then merge (vs failing on "not green").
|
|
295
|
+
if (sub === 'merge' && hasFlag(a, 'wait'))
|
|
296
|
+
body.waitForCi = true;
|
|
297
|
+
const run = await api.trigger(trig.path, body);
|
|
298
|
+
console.log(c.green(`started ${sub}${multi ? ` #${num}` : ''} → ${run.id.slice(0, 8)}`));
|
|
299
|
+
if (watch)
|
|
300
|
+
await watchRun(run.id);
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
//# sourceMappingURL=workflows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows.js","sourceRoot":"","sources":["../../src/commands/workflows.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, chmodSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join, dirname } from 'node:path';
|
|
4
|
+
import { parse } from './args.js';
|
|
5
|
+
/** Persisted CLI config (overridden by env vars). */
|
|
6
|
+
export const CONFIG_PATH = process.env.MOA_CONFIG || join(homedir(), '.moa', 'cli.json');
|
|
7
|
+
export const DEFAULT_URL = 'http://localhost:3000';
|
|
8
|
+
export function readConfig() {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(readFileSync(CONFIG_PATH, 'utf8'));
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return {};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function writeConfig(cfg) {
|
|
17
|
+
// The file holds the API key — owner-only perms on both dir and file.
|
|
18
|
+
mkdirSync(dirname(CONFIG_PATH), { recursive: true, mode: 0o700 });
|
|
19
|
+
writeFileSync(CONFIG_PATH, `${JSON.stringify(cfg, null, 2)}\n`, { mode: 0o600 });
|
|
20
|
+
try {
|
|
21
|
+
chmodSync(CONFIG_PATH, 0o600); // mode above only applies on create; fix pre-existing files
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
/* best effort */
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Mask a secret for display: first 8 chars + ellipsis. */
|
|
28
|
+
export const mask = (s) => (s.length > 8 ? `${s.slice(0, 8)}…` : s);
|
|
29
|
+
/** A global `--profile <name>` / `--profile=<name>` flag, read straight from argv
|
|
30
|
+
* (works even though profile resolution happens at import time). Highest precedence. */
|
|
31
|
+
function profileFlag() {
|
|
32
|
+
const v = parse(process.argv.slice(2)).flags.profile;
|
|
33
|
+
return typeof v === 'string' ? v.trim() || undefined : undefined;
|
|
34
|
+
}
|
|
35
|
+
/** The active profile name: `--profile` → `$MOA_PROFILE` → config.current → `default`. */
|
|
36
|
+
export function currentProfileName(cfg = readConfig()) {
|
|
37
|
+
return profileFlag() || process.env.MOA_PROFILE?.trim() || cfg.current || 'default';
|
|
38
|
+
}
|
|
39
|
+
/** Every named profile. */
|
|
40
|
+
export function listProfiles(cfg = readConfig()) {
|
|
41
|
+
return { ...(cfg.profiles ?? {}) };
|
|
42
|
+
}
|
|
43
|
+
/** Resolve the effective target for the active profile.
|
|
44
|
+
* Precedence per field: env var → the profile → default. */
|
|
45
|
+
export function resolveProfile(cfg = readConfig()) {
|
|
46
|
+
const name = currentProfileName(cfg);
|
|
47
|
+
const p = cfg.profiles?.[name] ?? {};
|
|
48
|
+
const apiUrl = (process.env.MOA_API_URL || p.apiUrl || DEFAULT_URL).replace(/\/$/, '');
|
|
49
|
+
const apiKey = process.env.MOA_API_KEY || p.apiKey || undefined;
|
|
50
|
+
return { name, apiUrl, apiKey };
|
|
51
|
+
}
|
|
52
|
+
/** Update one field on a named profile (creating it if absent) and persist. */
|
|
53
|
+
export function setProfileField(name, field, value) {
|
|
54
|
+
const cfg = readConfig();
|
|
55
|
+
cfg.profiles = cfg.profiles ?? {};
|
|
56
|
+
cfg.profiles[name] = { ...(cfg.profiles[name] ?? {}), [field]: value };
|
|
57
|
+
if (!cfg.current)
|
|
58
|
+
cfg.current = name;
|
|
59
|
+
writeConfig(cfg);
|
|
60
|
+
}
|
|
61
|
+
/** Persist a freshly-bootstrapped key onto the active profile. */
|
|
62
|
+
export function saveKeyToCurrent(apiKey) {
|
|
63
|
+
setProfileField(currentProfileName(), 'apiKey', apiKey);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=config.js.map
|