mergestorm 0.3.64 → 0.3.66
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 +28 -9
- package/dist/api.d.ts +63 -11
- package/dist/api.js +195 -6
- package/dist/automation-catalog.d.ts +5 -1
- package/dist/automation-catalog.js +1 -0
- package/dist/cli.js +21 -19
- package/dist/client/index.d.ts +3 -2
- package/dist/client/index.js +3 -2
- package/dist/commands/account.d.ts +3 -0
- package/dist/commands/account.js +75 -0
- package/dist/commands/browse.d.ts +1 -9
- package/dist/commands/browse.js +10 -8
- package/dist/commands/dismiss.d.ts +0 -2
- package/dist/commands/dismiss.js +2 -2
- package/dist/commands/help.js +3 -2
- package/dist/commands/issue.d.ts +24 -6
- package/dist/commands/issue.js +153 -31
- package/dist/commands/login.d.ts +2 -1
- package/dist/commands/login.js +50 -14
- package/dist/commands/logout.js +6 -7
- package/dist/commands/memory.d.ts +2 -3
- package/dist/commands/memory.js +8 -6
- package/dist/commands/registry.d.ts +1 -0
- package/dist/commands/registry.js +35 -11
- package/dist/commands/review-client.d.ts +0 -3
- package/dist/commands/review-client.js +3 -3
- package/dist/commands/review.d.ts +1 -1
- package/dist/commands/review.js +1 -1
- package/dist/commands/settings.d.ts +3 -5
- package/dist/commands/settings.js +4 -3
- package/dist/commands/stack.d.ts +19 -5
- package/dist/commands/stack.js +78 -4
- package/dist/commands/whoami.js +14 -10
- package/dist/config.d.ts +55 -2
- package/dist/config.js +264 -13
- package/dist/errors.d.ts +1 -1
- package/dist/gh.d.ts +0 -4
- package/dist/gh.js +4 -4
- package/dist/git.d.ts +1 -1
- package/dist/git.js +2 -2
- package/dist/memory-api.d.ts +1 -0
- package/dist/memory-api.js +2 -2
- package/dist/node-version.d.ts +0 -2
- package/dist/node-version.js +1 -1
- package/dist/pr-body.d.ts +4 -0
- package/dist/pr-body.js +15 -0
- package/dist/repo-identity.d.ts +2 -1
- package/dist/repo-identity.js +8 -4
- package/dist/server-publish.d.ts +1 -24
- package/dist/server-publish.js +9 -9
- package/dist/stack-blockers.d.ts +12 -38
- package/dist/stack-blockers.js +55 -33
- package/dist/stack-dto.d.ts +3 -0
- package/dist/stack-dto.js +15 -2
- package/dist/stack-meta.d.ts +2 -2
- package/dist/stack-meta.js +1 -1
- package/dist/stack-watch-loop.d.ts +2 -13
- package/dist/stack-watch-loop.js +12 -12
- package/dist/submit-pr-base.d.ts +0 -1
- package/dist/submit-pr-base.js +1 -1
- package/dist/ui/ansi.d.ts +0 -10
- package/dist/ui/ansi.js +2 -2
- package/dist/ui/banner.d.ts +3 -1
- package/dist/ui/banner.js +10 -3
- package/dist/ui/box.d.ts +0 -2
- package/dist/ui/box.js +1 -1
- package/dist/ui/prompt.d.ts +0 -11
- package/dist/ui/prompt.js +7 -7
- package/dist/ui/tabs.d.ts +2 -2
- package/dist/ui/tabs.js +1 -1
- package/dist/ui/width.d.ts +0 -9
- package/dist/ui/width.js +3 -3
- package/dist/web-api.d.ts +17 -0
- package/dist/web-api.js +30 -0
- package/package.json +1 -1
- package/skill/SKILL.md +4 -0
- package/skill/mergestorm-bounce-watch/SKILL.md +1 -1
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { type Config } from "../config.js";
|
|
2
2
|
import { deleteMemory, getMemoryMode, listMemories, saveMemory, searchMemories, setMemoryMode, updateMemory, type MemoryItem, type MemoryKind, type MemoryScope } from "../memory-api.js";
|
|
3
|
-
export declare const MEMORY_USAGE: string;
|
|
4
|
-
export declare const MEMORY_SUBCOMMANDS: readonly ["list", "search", "add", "update", "delete", "mode"];
|
|
5
3
|
type Flags = {
|
|
6
4
|
positional: string[];
|
|
7
5
|
json: boolean;
|
|
6
|
+
keepBoth?: boolean;
|
|
8
7
|
repo?: string;
|
|
9
8
|
kind?: MemoryKind;
|
|
10
9
|
scope?: MemoryScope;
|
|
11
10
|
limit?: number;
|
|
12
11
|
};
|
|
13
|
-
export declare function parseMemoryFlags(args: string[], allowed: ReadonlyArray<"repo" | "kind" | "scope" | "limit">): Flags;
|
|
12
|
+
export declare function parseMemoryFlags(args: string[], allowed: ReadonlyArray<"repo" | "kind" | "scope" | "limit" | "keep-both">): Flags;
|
|
14
13
|
export declare function formatMemoryLine(memory: MemoryItem): string;
|
|
15
14
|
export type MemoryDeps = {
|
|
16
15
|
loadConfig?: () => Promise<Config>;
|
package/dist/commands/memory.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { loadConfig } from "../config.js";
|
|
2
2
|
import { CommandError, REVIEW_EXIT } from "../errors.js";
|
|
3
3
|
import { MEMORY_KINDS, MEMORY_SEARCH_LIMIT_MAX, deleteMemory, getMemoryMode, isMemoryKind, isMemoryMode, isMemoryScope, listMemories, memoryChatId, saveMemory, searchMemories, setMemoryMode, updateMemory, } from "../memory-api.js";
|
|
4
|
-
|
|
4
|
+
const MEMORY_USAGE = [
|
|
5
5
|
"usage: mergestorm memory list [--scope user|repo] [--repo <owner/repo>] [--kind <kind>] [--json]",
|
|
6
6
|
" mergestorm memory search <query> [--repo <owner/repo>] [--limit <1-20>] [--json]",
|
|
7
|
-
" mergestorm memory add <text> --kind <kind> [--repo <owner/repo>] [--json]",
|
|
7
|
+
" mergestorm memory add <text> --kind <kind> [--repo <owner/repo>] [--keep-both] [--json]",
|
|
8
8
|
" mergestorm memory update <id> <text> [--kind <kind>] [--json]",
|
|
9
9
|
" mergestorm memory delete <id> [--json]",
|
|
10
10
|
" mergestorm memory mode [off|on_request|all] [--json]",
|
|
11
11
|
` kind is one of ${MEMORY_KINDS.join(", ")}. With --repo a memory is about that repository, otherwise about you.`,
|
|
12
|
+
" add refuses text close to a memory you have; update that memory, or add again with --keep-both when they are different things.",
|
|
12
13
|
" search covers your memories, and with --repo that repository's memories and standing rules too.",
|
|
13
14
|
" Inside a Breeze chat (MERGESTORM_CHAT_ID), add and search follow that chat's memory setting.",
|
|
14
15
|
].join("\n");
|
|
15
|
-
export const MEMORY_SUBCOMMANDS = ["list", "search", "add", "update", "delete", "mode"];
|
|
16
16
|
const REPO = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})\/[A-Za-z0-9._-]{1,100}$/;
|
|
17
17
|
function usage(message) {
|
|
18
18
|
return new CommandError(message ? `${message}\n${MEMORY_USAGE}` : MEMORY_USAGE, REVIEW_EXIT.usage, "usage");
|
|
@@ -29,6 +29,8 @@ export function parseMemoryFlags(args, allowed) {
|
|
|
29
29
|
const name = arg.startsWith("--") ? arg.slice(2) : null;
|
|
30
30
|
if (arg === "--json")
|
|
31
31
|
flags.json = true;
|
|
32
|
+
else if (name === "keep-both" && allowed.includes("keep-both"))
|
|
33
|
+
flags.keepBoth = true;
|
|
32
34
|
else if (name === "repo" && allowed.includes("repo")) {
|
|
33
35
|
const repo = value(arg, args[++i]).replace(/^https?:\/\/github\.com\//i, "").replace(/\.git$/i, "");
|
|
34
36
|
if (!REPO.test(repo))
|
|
@@ -108,14 +110,14 @@ export async function cmdMemory(args, deps = {}) {
|
|
|
108
110
|
return;
|
|
109
111
|
}
|
|
110
112
|
if (sub === "add" || sub === "save" || sub === "remember") {
|
|
111
|
-
const flags = parseMemoryFlags(rest, ["repo", "kind"]);
|
|
113
|
+
const flags = parseMemoryFlags(rest, ["repo", "kind", "keep-both"]);
|
|
112
114
|
const text = flags.positional.join(" ").trim();
|
|
113
115
|
if (!text)
|
|
114
116
|
throw usage("add needs the text to remember");
|
|
115
117
|
if (!flags.kind)
|
|
116
118
|
throw usage(`add needs --kind (${MEMORY_KINDS.join(", ")})`);
|
|
117
|
-
const saved = await api.saveMemory({ text, kind: flags.kind, ...(flags.repo ? { repo: flags.repo } : {}), chatId }, await config());
|
|
118
|
-
emit(flags.json, saved, () => [saved.merged ? `
|
|
119
|
+
const saved = await api.saveMemory({ text, kind: flags.kind, ...(flags.repo ? { repo: flags.repo } : {}), chatId, ...(flags.keepBoth ? { keepBoth: true } : {}) }, await config());
|
|
120
|
+
emit(flags.json, saved, () => [saved.merged ? `Memory ${saved.id} already says this.` : `Saved to memory as ${saved.id}.`]);
|
|
119
121
|
return;
|
|
120
122
|
}
|
|
121
123
|
if (sub === "update" || sub === "edit") {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { DEFAULT_API } from "../config.js";
|
|
1
|
+
import { DEFAULT_API, splitAccountFlag, withAccount } from "../config.js";
|
|
2
2
|
import { CommandError } from "../errors.js";
|
|
3
|
+
import { cmdAccount } from "./account.js";
|
|
3
4
|
import { cmdBranches, cmdChain } from "./branches.js";
|
|
4
5
|
import { canBrowse, openTabsBrowser } from "./browse.js";
|
|
5
6
|
import { cmdCredits } from "./credits.js";
|
|
@@ -24,9 +25,9 @@ import { cmdWhoami } from "./whoami.js";
|
|
|
24
25
|
export const COMMAND_REGISTRY = [
|
|
25
26
|
{
|
|
26
27
|
name: "login",
|
|
27
|
-
summary: "Sign in via browser (or paste a key)",
|
|
28
|
+
summary: "Sign in via browser (or paste a key); adds an account, up to 3",
|
|
28
29
|
usage: [
|
|
29
|
-
"mergestorm login Sign in via browser and
|
|
30
|
+
"mergestorm login Sign in via browser and add the account (up to 3 saved)",
|
|
30
31
|
"mergestorm login --start Print a sign-in URL and code, then exit (agents)",
|
|
31
32
|
"mergestorm login --finish Store the API key once the code from --start is approved",
|
|
32
33
|
"mergestorm login --key Paste an existing API key instead (headless/CI)",
|
|
@@ -39,14 +40,28 @@ export const COMMAND_REGISTRY = [
|
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
42
|
name: "logout",
|
|
42
|
-
summary: "
|
|
43
|
-
usage: ["mergestorm logout
|
|
43
|
+
summary: "Log out of the active account and revoke its key",
|
|
44
|
+
usage: ["mergestorm logout Log out of the active account (or --account <name>) and revoke its key"],
|
|
44
45
|
async run(_args, ctx) {
|
|
45
46
|
await cmdLogout();
|
|
46
47
|
if (ctx.afterAuth)
|
|
47
48
|
await ctx.afterAuth();
|
|
48
49
|
},
|
|
49
50
|
},
|
|
51
|
+
{
|
|
52
|
+
name: "account",
|
|
53
|
+
summary: "Saved accounts: list, use <name>, remove <name>",
|
|
54
|
+
usage: [
|
|
55
|
+
"mergestorm account list [--json] Saved accounts (up to 3), the active one marked",
|
|
56
|
+
"mergestorm account use <name> Make <name> the active account",
|
|
57
|
+
"mergestorm account remove <name> Log out of <name> and revoke its key",
|
|
58
|
+
],
|
|
59
|
+
async run(args, ctx) {
|
|
60
|
+
await cmdAccount(args);
|
|
61
|
+
if (ctx.afterAuth)
|
|
62
|
+
await ctx.afterAuth();
|
|
63
|
+
},
|
|
64
|
+
},
|
|
50
65
|
{
|
|
51
66
|
name: "review",
|
|
52
67
|
summary: "Review git diff (default origin/HEAD or main or master)",
|
|
@@ -102,11 +117,15 @@ export const COMMAND_REGISTRY = [
|
|
|
102
117
|
},
|
|
103
118
|
{
|
|
104
119
|
name: "issue",
|
|
105
|
-
summary: "Open a GitHub issue through Mergestorm
|
|
120
|
+
summary: "Open a GitHub issue through Mergestorm and wait for its Vortex review",
|
|
106
121
|
usage: [
|
|
107
|
-
"mergestorm issue create --title <title> [--body <text> | --body-file <path>] [--label <name>]… [--repo <owner/repo>] [--json]",
|
|
122
|
+
"mergestorm issue create --title <title> [--body <text> | --body-file <path>] [--label <name>]… [--repo <owner/repo>] [--wait [--timeout <s>]] [--json]",
|
|
108
123
|
" Opens the issue as the Surge App; needs write access on GitHub, uses existing labels only",
|
|
109
124
|
" The same title again returns the open issue it already made when it is among the newest 100 open issues; an older one, or two calls at once, can still create a duplicate",
|
|
125
|
+
" --wait then waits for the Vortex issue review, like issue wait",
|
|
126
|
+
"mergestorm issue wait <n> [--repo <owner/repo>] [--timeout <s>] [--json]",
|
|
127
|
+
" Waits for the Vortex issue review (default 900s); exits 0 once approved or when issue reviews are off",
|
|
128
|
+
" Exits 4 with the points to answer: reply in a comment on the issue, wait again, and open the PR only after approval",
|
|
110
129
|
],
|
|
111
130
|
async run(args) {
|
|
112
131
|
await cmdIssue(args);
|
|
@@ -186,7 +205,7 @@ export const COMMAND_REGISTRY = [
|
|
|
186
205
|
{
|
|
187
206
|
name: "whoami",
|
|
188
207
|
summary: "Key + plan (Status tab on a TTY)",
|
|
189
|
-
usage: ["mergestorm whoami [--json]
|
|
208
|
+
usage: ["mergestorm whoami [--json] Account + key + plan + API base"],
|
|
190
209
|
async run(args, ctx) {
|
|
191
210
|
await cmdWhoami(args, { mode: ctx.mode });
|
|
192
211
|
},
|
|
@@ -201,6 +220,7 @@ export const COMMAND_REGISTRY = [
|
|
|
201
220
|
" [--cyclone-skip-ci on|off]",
|
|
202
221
|
" [--cyclone-patch-unverified on|off] Patch languages we cannot typecheck",
|
|
203
222
|
" [--vortex-seam on|off] [--vortex-skip-all-clear on|off]",
|
|
223
|
+
" [--issue-review on|off] Account default for Vortex issue reviews; --repo overrides it per repository",
|
|
204
224
|
" [--auto-land on|off] Auto land default for new stacks",
|
|
205
225
|
" [--auto-land-settle <seconds>] How long Auto land waits before queueing (15-300, default 60)",
|
|
206
226
|
" [--merge-queue-batch on|off] Test several queued pull requests on one CI run",
|
|
@@ -225,7 +245,7 @@ export const COMMAND_REGISTRY = [
|
|
|
225
245
|
usage: [
|
|
226
246
|
"mergestorm memory list [--scope user|repo] [--repo <owner/repo>] [--kind <kind>] [--json]",
|
|
227
247
|
"mergestorm memory search <query> [--repo <owner/repo>] [--limit <1-20>] [--json]",
|
|
228
|
-
"mergestorm memory add <text> --kind rule|style|preference|fact|project [--repo <owner/repo>] [--json]",
|
|
248
|
+
"mergestorm memory add <text> --kind rule|style|preference|fact|project [--repo <owner/repo>] [--keep-both] [--json]",
|
|
229
249
|
"mergestorm memory update <id> <text> [--kind <kind>] [--json]",
|
|
230
250
|
"mergestorm memory delete <id> [--json]",
|
|
231
251
|
"mergestorm memory mode [off|on_request|all] [--json] Read or set whether Breeze remembers",
|
|
@@ -348,9 +368,12 @@ export function formatUsageBody() {
|
|
|
348
368
|
return `${cmdLines}
|
|
349
369
|
|
|
350
370
|
mg is a short alias for mergestorm (same binary).
|
|
371
|
+
--account <name> before or after any command runs it as that saved account
|
|
372
|
+
without changing the active one; MERGESTORM_ACCOUNT=<name> does the same.
|
|
351
373
|
|
|
352
374
|
Env:
|
|
353
|
-
MERGESTORM_API_KEY API key (overrides
|
|
375
|
+
MERGESTORM_API_KEY API key (overrides every saved account)
|
|
376
|
+
MERGESTORM_ACCOUNT Saved account to run as (default: the active one)
|
|
354
377
|
MERGESTORM_API_URL API base (default ${DEFAULT_API})
|
|
355
378
|
MERGESTORM_HOME State directory for login and stack state (default ~/.mergestorm)
|
|
356
379
|
`;
|
|
@@ -366,6 +389,7 @@ export async function dispatchCommand(name, args, ctx) {
|
|
|
366
389
|
// `shell` as a subcommand is oneshot-only.
|
|
367
390
|
if (cmd.name === "shell" && ctx.mode === "shell")
|
|
368
391
|
return false;
|
|
369
|
-
|
|
392
|
+
const split = splitAccountFlag(args);
|
|
393
|
+
await withAccount(split.account ?? ctx.account, () => cmd.run(split.args, ctx));
|
|
370
394
|
return true;
|
|
371
395
|
}
|
|
@@ -10,10 +10,8 @@ export declare const REVIEW_POLL_STRETCH_AFTER_MS = 60000;
|
|
|
10
10
|
export declare const REVIEW_POLL_STRETCH_SPAN_MS = 60000;
|
|
11
11
|
/** Same thread slug contract as POST /api/v1/reviews. */
|
|
12
12
|
export declare const REVIEW_THREAD_SLUG_RE: RegExp;
|
|
13
|
-
export declare const MAX_CONTEXT_TEXT_CHARS = 60000;
|
|
14
13
|
export declare const MAX_CONTEXT_FILES = 10;
|
|
15
14
|
export declare const MAX_CONTEXT_FILE_CHARS = 16000;
|
|
16
|
-
export declare const MAX_CONTEXT_FILES_TOTAL = 60000;
|
|
17
15
|
export declare const MAX_IDEMPOTENCY_KEY_CHARS = 128;
|
|
18
16
|
export type ReviewInput = {
|
|
19
17
|
thread: string;
|
|
@@ -57,7 +55,6 @@ export type LoadReviewContextOptions = {
|
|
|
57
55
|
};
|
|
58
56
|
/** Load --context / --context-file and enforce the API caps client-side. */
|
|
59
57
|
export declare function loadReviewContext(opts: LoadReviewContextOptions): Promise<ReviewContextPayload>;
|
|
60
|
-
export declare function reviewIdempotencyKey(input: ReviewInput, opts?: SubmitReviewOptions, afterJobId?: string | null): string;
|
|
61
58
|
export declare function submitReview(cfg: Config, input: ReviewInput, opts?: SubmitReviewOptions): Promise<{
|
|
62
59
|
status: number;
|
|
63
60
|
row: ReviewJobRow;
|
|
@@ -13,10 +13,10 @@ export const REVIEW_POLL_STRETCH_AFTER_MS = 60_000;
|
|
|
13
13
|
export const REVIEW_POLL_STRETCH_SPAN_MS = 60_000;
|
|
14
14
|
/** Same thread slug contract as POST /api/v1/reviews. */
|
|
15
15
|
export const REVIEW_THREAD_SLUG_RE = /^[a-zA-Z0-9][a-zA-Z0-9._/-]{0,119}$/;
|
|
16
|
-
|
|
16
|
+
const MAX_CONTEXT_TEXT_CHARS = 60_000;
|
|
17
17
|
export const MAX_CONTEXT_FILES = 10;
|
|
18
18
|
export const MAX_CONTEXT_FILE_CHARS = 16_000;
|
|
19
|
-
|
|
19
|
+
const MAX_CONTEXT_FILES_TOTAL = 60_000;
|
|
20
20
|
export const MAX_IDEMPOTENCY_KEY_CHARS = 128;
|
|
21
21
|
export async function collectReviewInput(base, head, cwd = process.cwd(), sandboxRoot) {
|
|
22
22
|
let diff;
|
|
@@ -129,7 +129,7 @@ export async function loadReviewContext(opts) {
|
|
|
129
129
|
}
|
|
130
130
|
const REPLAYED_JOB_RESUBMIT_STATUSES = ["failed", "quota_exceeded"];
|
|
131
131
|
const MAX_REPLAYED_JOB_RESUBMITS = 5;
|
|
132
|
-
|
|
132
|
+
function reviewIdempotencyKey(input, opts = {}, afterJobId = null) {
|
|
133
133
|
const request = [
|
|
134
134
|
input.thread, input.branch, input.repo ?? null, input.baseLabel, input.headLabel, input.diff, input.files,
|
|
135
135
|
opts.routerMode ?? null, [...new Set(opts.specialists ?? [])].sort(), opts.context ?? null, opts.contextFiles ?? [], opts.webhookUrl ?? null,
|
|
@@ -10,7 +10,7 @@ export declare const VORTEX_ROUTER_CAPS: {
|
|
|
10
10
|
/**
|
|
11
11
|
* Pinnable L0 lanes only. Keep this list byte-identical to
|
|
12
12
|
* `pinnableVortexSpecialistIds(VORTEX_SPECIALIST_IDS)` in review-findings
|
|
13
|
-
* (`
|
|
13
|
+
* (`index.test.ts`). Do not add `governance` (round-gated) or `seam`
|
|
14
14
|
* (phase-gated). Those L1 lanes are not local pins.
|
|
15
15
|
*/
|
|
16
16
|
export declare const VORTEX_SPECIALIST_IDS: readonly ["security", "performance", "architecture", "tests", "data", "api", "frontend"];
|
package/dist/commands/review.js
CHANGED
|
@@ -16,7 +16,7 @@ export const VORTEX_ROUTER_CAPS = { standard: 3, max: 5 };
|
|
|
16
16
|
/**
|
|
17
17
|
* Pinnable L0 lanes only. Keep this list byte-identical to
|
|
18
18
|
* `pinnableVortexSpecialistIds(VORTEX_SPECIALIST_IDS)` in review-findings
|
|
19
|
-
* (`
|
|
19
|
+
* (`index.test.ts`). Do not add `governance` (round-gated) or `seam`
|
|
20
20
|
* (phase-gated). Those L1 lanes are not local pins.
|
|
21
21
|
*/
|
|
22
22
|
export const VORTEX_SPECIALIST_IDS = [
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type RepoSettingsPatch, type SettingsPatch, type SettingsResponse } from "../api.js";
|
|
2
2
|
/**
|
|
3
3
|
* CLI flag → Bearer settings key. Boolean flags take on|off. The connected flags are
|
|
4
4
|
* read-only on the API and deliberately have no flag here.
|
|
5
5
|
*/
|
|
6
|
-
export declare const SETTINGS_FLAGS: Record<string, "auto_review_enabled" | "auto_patch_enabled" | "auto_resolve_conflicts_enabled" | "auto_fix_ci_enabled" | "vortex_show_thinking_traces" | "repo_overview_enabled" | "cyclone_skip_ci_enabled" | "cyclone_patch_unverified_languages" | "vortex_auto_overflow_enabled" | "vortex_skip_all_clear_comments" | "vortex_seam_specialist_enabled" | "auto_land_default" | "auto_land_settle_seconds" | "merge_queue_batch_enabled" | "merge_queue_batch_size" | "merge_queue_lands_alone_paths" | "merge_queue_overdrive" | "ignored_bot_logins" | "vortex_bot_skip_check" | "vortex_findings_check" | "cyclone_patch_failure_check">;
|
|
6
|
+
export declare const SETTINGS_FLAGS: Record<string, "auto_review_enabled" | "auto_patch_enabled" | "auto_resolve_conflicts_enabled" | "auto_fix_ci_enabled" | "vortex_show_thinking_traces" | "repo_overview_enabled" | "cyclone_skip_ci_enabled" | "cyclone_patch_unverified_languages" | "vortex_auto_overflow_enabled" | "vortex_skip_all_clear_comments" | "vortex_seam_specialist_enabled" | "issue_review_enabled" | "auto_land_default" | "auto_land_settle_seconds" | "merge_queue_batch_enabled" | "merge_queue_batch_size" | "merge_queue_lands_alone_paths" | "merge_queue_overdrive" | "ignored_bot_logins" | "vortex_bot_skip_check" | "vortex_findings_check" | "cyclone_patch_failure_check">;
|
|
7
7
|
type IgnoreBotOperation = {
|
|
8
8
|
action: "add" | "remove";
|
|
9
9
|
login: string;
|
|
10
10
|
} | {
|
|
11
11
|
action: "clear";
|
|
12
12
|
};
|
|
13
|
-
|
|
13
|
+
type RepoSettingsScope = {
|
|
14
14
|
owner: string;
|
|
15
15
|
repo: string;
|
|
16
16
|
patch: RepoSettingsPatch;
|
|
@@ -22,8 +22,6 @@ export type SettingsArgs = {
|
|
|
22
22
|
repo?: RepoSettingsScope;
|
|
23
23
|
listRepos?: boolean;
|
|
24
24
|
};
|
|
25
|
-
export declare function parsePathsFlagValue(flag: string, value: string | undefined, defaults: readonly string[]): string[];
|
|
26
|
-
export declare function formatRepoSettingsLines(repos: readonly RepoSettings[]): string[];
|
|
27
25
|
/** Parse boolean and enum flags plus ordered ignore-list operations. */
|
|
28
26
|
export declare function parseSettingsArgs(rawArgs: string[]): SettingsArgs;
|
|
29
27
|
/** Static printout includes the Config toggles plus enum and login settings. */
|
|
@@ -18,8 +18,9 @@ const REPO_FLAG_LABELS = {
|
|
|
18
18
|
merge_queue_batch_size: "Merge queue batch size (pull requests)",
|
|
19
19
|
merge_queue_lands_alone_paths: "Merge queue lands-alone paths",
|
|
20
20
|
merge_queue_overdrive: "Merge queue overdrive",
|
|
21
|
+
issue_review_enabled: "Vortex issue reviews",
|
|
21
22
|
};
|
|
22
|
-
|
|
23
|
+
function parsePathsFlagValue(flag, value, defaults) {
|
|
23
24
|
if (value === undefined || value === "" || value.startsWith("--")) {
|
|
24
25
|
throw new CommandError(`${flag} takes a comma-separated list of path patterns, default, or none.`, 2, "usage");
|
|
25
26
|
}
|
|
@@ -79,7 +80,7 @@ function parseRepoSettingsArgs(slug, args) {
|
|
|
79
80
|
throw new CommandError(`Unknown settings flag: ${flag}. See \`mergestorm --help\`.`, 2, "usage");
|
|
80
81
|
}
|
|
81
82
|
if (!REPO_SETTINGS_KEYS.includes(key)) {
|
|
82
|
-
throw new CommandError(`${flag} is an account setting. With --repo only --auto-patch, --auto-review, --auto-land, --merge-queue-batch, --merge-queue-batch-size, --merge-queue-lands-alone
|
|
83
|
+
throw new CommandError(`${flag} is an account setting. With --repo only --auto-patch, --auto-review, --auto-land, --merge-queue-batch, --merge-queue-batch-size, --merge-queue-lands-alone, --merge-queue-overdrive and --issue-review can be set.`, 2, "usage");
|
|
83
84
|
}
|
|
84
85
|
const value = eq >= 0 ? arg.slice(eq + 1) : args[++i];
|
|
85
86
|
const row = BEARER_SETTINGS.find((row) => row.key === key);
|
|
@@ -115,7 +116,7 @@ function repoSettingWords(value) {
|
|
|
115
116
|
return String(value);
|
|
116
117
|
return value ? "on" : "off";
|
|
117
118
|
}
|
|
118
|
-
|
|
119
|
+
function formatRepoSettingsLines(repos) {
|
|
119
120
|
if (repos.length === 0)
|
|
120
121
|
return [" No repositories are connected to this account."];
|
|
121
122
|
const width = Math.max(...Object.values(REPO_FLAG_LABELS).map((label) => label.length));
|
package/dist/commands/stack.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type StackRepairHint } from "../stack-blockers.js";
|
|
2
2
|
import { type StackWatchObligation } from "../stack-watch-obligation.js";
|
|
3
|
-
import { adoptStack, ensureUpperPark, findStackPull, getEnrichedStack, getStackPublication, listMergeQueueEntries, listStacks, openStackPull, claimStackPulls, setStackPolicy, type StackDto, type StackPolicyPatch } from "../api.js";
|
|
3
|
+
import { adoptStack, ensureUpperPark, findStackPull, getEnrichedStack, getIssueReview, getStackPublication, listMergeQueueEntries, listStacks, openStackPull, claimStackPulls, setStackPolicy, type StackDto, type StackPolicyPatch } from "../api.js";
|
|
4
4
|
import { loadConfig } from "../config.js";
|
|
5
5
|
import { createPrs, findOpenPrNumber } from "../gh.js";
|
|
6
6
|
import { parseGithubOriginRepo } from "../git.js";
|
|
@@ -11,9 +11,7 @@ import { gitTopLevel } from "../repo-identity.js";
|
|
|
11
11
|
import { loadStackMeta, saveStackMeta } from "../stack-meta.js";
|
|
12
12
|
import { pollStackWatch } from "../stack-watch.js";
|
|
13
13
|
import { runStackWatch } from "../stack-watch-loop.js";
|
|
14
|
-
export declare function stackHeldLine(held: StackHeldBlocker | null | undefined): string[];
|
|
15
14
|
export declare function stackRepairLine(repair: StackRepairHint | null | undefined): string[];
|
|
16
|
-
export declare function stackWatchTextLines(watch: StackWatchObligation | null | undefined): string[];
|
|
17
15
|
export declare function openStackWatch(stackId: string, opts?: {
|
|
18
16
|
unread?: boolean;
|
|
19
17
|
}): StackWatchObligation;
|
|
@@ -128,6 +126,22 @@ export type StackCreateDeps = {
|
|
|
128
126
|
};
|
|
129
127
|
export declare function cmdStackCreate(args: string[], deps?: StackCreateDeps): Promise<void>;
|
|
130
128
|
/** Injectable seams for unit tests (STRUCT-04). Production callers omit deps. */
|
|
129
|
+
export declare function issueReviewsEnabledFor(cfg: Awaited<ReturnType<typeof loadConfig>>, owner: string, repo: string): Promise<boolean>;
|
|
130
|
+
export type IssueGateLayer = {
|
|
131
|
+
branch: string;
|
|
132
|
+
texts: string[];
|
|
133
|
+
};
|
|
134
|
+
export type IssueGateDeps = {
|
|
135
|
+
getIssueReview?: typeof getIssueReview;
|
|
136
|
+
issueReviewsEnabled?: typeof issueReviewsEnabledFor;
|
|
137
|
+
};
|
|
138
|
+
export declare function assertLinkedIssuesApproved(input: {
|
|
139
|
+
cfg: Awaited<ReturnType<typeof loadConfig>>;
|
|
140
|
+
owner: string;
|
|
141
|
+
repo: string;
|
|
142
|
+
layers: readonly IssueGateLayer[];
|
|
143
|
+
warn: (line: string) => void;
|
|
144
|
+
}, deps?: IssueGateDeps): Promise<void>;
|
|
131
145
|
export type StackSubmitDeps = {
|
|
132
146
|
cwd?: string;
|
|
133
147
|
gitTopLevel?: (cwd?: string) => string;
|
|
@@ -155,7 +169,7 @@ export type StackSubmitDeps = {
|
|
|
155
169
|
adoptStack?: typeof adoptStack;
|
|
156
170
|
ensureUpperPark?: typeof ensureUpperPark;
|
|
157
171
|
env?: NodeJS.ProcessEnv;
|
|
158
|
-
};
|
|
172
|
+
} & IssueGateDeps;
|
|
159
173
|
export declare function cmdStackSubmit(args: string[], deps?: StackSubmitDeps): Promise<void>;
|
|
160
174
|
export declare function parseStackPublishArgs(args: string[]): {
|
|
161
175
|
branch?: string;
|
package/dist/commands/stack.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { cycloneStatusWords, stackBlockers, stackBlockersSummary } from "../stack-blockers.js";
|
|
2
2
|
import { STACK_WATCH_NOT_DONE_SENTENCE, STACK_WATCH_NOTIFY_PATTERN, stackTerminalReason, stackWatchObligation, } from "../stack-watch-obligation.js";
|
|
3
|
-
import { adoptStack, ensureUpperPark, findStackPull, getEnrichedStack, getStackPublication, landNextStack, listMergeQueueEntries, listStacks, openStackPull, claimStackPulls, restackStack, setStackPolicy, } from "../api.js";
|
|
3
|
+
import { adoptStack, ensureUpperPark, findStackPull, getEnrichedStack, getIssueReview, getSettings, getStackPublication, issueNotApprovedError, landNextStack, listRepoSettings, listMergeQueueEntries, listStacks, openStackPull, claimStackPulls, restackStack, setStackPolicy, } from "../api.js";
|
|
4
4
|
import { loadConfig } from "../config.js";
|
|
5
5
|
import { rateLimitedMessage, REVIEW_EXIT, CommandError } from "../errors.js";
|
|
6
6
|
import { createPrs, findOpenPrNumber, ghReady, githubApiFromEnv, } from "../gh.js";
|
|
7
7
|
import { parseGithubOriginRepo } from "../git.js";
|
|
8
8
|
import { branchExists, commitsAheadOf, createBranchFrom, createBranchFromHead, trunkStartRef, currentBranch, defaultLayerBranchName, deleteBranch, discoverTrunk, fetchRemoteBranch, pushBranch, tipCommitMessage, tipCommitSubject, worktreeDirty, } from "../git-stack.js";
|
|
9
|
-
import { buildPrBodyFromCommit } from "../pr-body.js";
|
|
9
|
+
import { buildPrBodyFromCommit, linkedIssueNumbers } from "../pr-body.js";
|
|
10
10
|
import { publishBranchServerSide, assertExplicitStacking, publishWorkingBranch, workingBranchPublication, } from "../server-publish.js";
|
|
11
11
|
import { gitTopLevel } from "../repo-identity.js";
|
|
12
12
|
import { activeLayers, appendLayer, emptyStackMeta, loadStackMeta, removeActiveStack, resetStackMeta, saveStackMeta, selectStackForCreate, setActivePolicy, } from "../stack-meta.js";
|
|
@@ -19,7 +19,7 @@ import { present } from "../ui/present.js";
|
|
|
19
19
|
import { canBrowse } from "./browse.js";
|
|
20
20
|
import { isTransientReviewPollError } from "./review-client.js";
|
|
21
21
|
import { openHelpBrowser } from "./help.js";
|
|
22
|
-
|
|
22
|
+
function stackHeldLine(held) {
|
|
23
23
|
if (!held)
|
|
24
24
|
return [];
|
|
25
25
|
const agents = held.waitingOn.map((agent) => agent === "cyclone" ? "Cyclone" : "Vortex").join(" and ");
|
|
@@ -32,7 +32,7 @@ export function stackRepairLine(repair) {
|
|
|
32
32
|
const note = "note" in repair && repair.note ? ` ${repair.note}` : "";
|
|
33
33
|
return [`Repair #${repair.prNumber} ${repair.kind}${files}: ${repair.steps}${note}`];
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
function stackWatchTextLines(watch) {
|
|
36
36
|
if (!watch)
|
|
37
37
|
return [];
|
|
38
38
|
if (watch.done)
|
|
@@ -680,6 +680,65 @@ export async function cmdStackCreate(args, deps = {}) {
|
|
|
680
680
|
created.push(ansi.dim(" authoring state: managed automatically outside the repository"));
|
|
681
681
|
await present("Stack", created);
|
|
682
682
|
}
|
|
683
|
+
/** Injectable seams for unit tests (STRUCT-04). Production callers omit deps. */
|
|
684
|
+
export async function issueReviewsEnabledFor(cfg, owner, repo) {
|
|
685
|
+
const repos = await listRepoSettings(cfg, { timeoutMs: STACK_GUARD_TIMEOUT_MS });
|
|
686
|
+
const row = repos.find((r) => r.owner.toLowerCase() === owner.toLowerCase() && r.repo.toLowerCase() === repo.toLowerCase());
|
|
687
|
+
if (typeof row?.issue_review_enabled === "boolean")
|
|
688
|
+
return row.issue_review_enabled;
|
|
689
|
+
const settings = await getSettings(cfg, { timeoutMs: STACK_GUARD_TIMEOUT_MS });
|
|
690
|
+
if (!settings)
|
|
691
|
+
throw new CommandError("Could not read the account settings");
|
|
692
|
+
return settings.issue_review_enabled === true;
|
|
693
|
+
}
|
|
694
|
+
export async function assertLinkedIssuesApproved(input, deps = {}) {
|
|
695
|
+
const { cfg, owner, repo, layers, warn } = input;
|
|
696
|
+
if (layers.length === 0)
|
|
697
|
+
return;
|
|
698
|
+
const getIssueReviewFn = deps.getIssueReview ?? getIssueReview;
|
|
699
|
+
const unverified = (err) => {
|
|
700
|
+
if (err instanceof CommandError && (err.code === "auth_invalid" || err.code === "missing_api_key" || err.code === "rate_limited"))
|
|
701
|
+
return err;
|
|
702
|
+
return new CommandError(`Could not verify the Vortex reviews of the linked issues (${err instanceof Error ? err.message : String(err)}); ` +
|
|
703
|
+
"refusing to submit. Retry when the API is reachable.");
|
|
704
|
+
};
|
|
705
|
+
const linked = layers.map((layer) => ({ branch: layer.branch, numbers: linkedIssueNumbers({ owner, repo }, ...layer.texts) }));
|
|
706
|
+
const statuses = [];
|
|
707
|
+
for (const number of [...new Set(linked.flatMap((layer) => layer.numbers))].sort((a, b) => a - b)) {
|
|
708
|
+
let status;
|
|
709
|
+
try {
|
|
710
|
+
status = await getIssueReviewFn(cfg, { owner, repo, number }, { timeoutMs: STACK_GUARD_TIMEOUT_MS });
|
|
711
|
+
}
|
|
712
|
+
catch (err) {
|
|
713
|
+
throw unverified(err);
|
|
714
|
+
}
|
|
715
|
+
if (!status) {
|
|
716
|
+
warn(ansi.dim(" This Mergestorm server does not check issue reviews yet; submitting without the issue gate."));
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
statuses.push(status);
|
|
720
|
+
}
|
|
721
|
+
const unlinked = linked.filter((layer) => layer.numbers.length === 0);
|
|
722
|
+
if (unlinked.length > 0) {
|
|
723
|
+
let enabled;
|
|
724
|
+
try {
|
|
725
|
+
enabled = await (deps.issueReviewsEnabled ?? issueReviewsEnabledFor)(cfg, owner, repo);
|
|
726
|
+
}
|
|
727
|
+
catch (err) {
|
|
728
|
+
throw unverified(err);
|
|
729
|
+
}
|
|
730
|
+
if (enabled) {
|
|
731
|
+
throw new CommandError([
|
|
732
|
+
`Issue reviews are on for ${owner}/${repo}, and ${unlinked.map((layer) => layer.branch).join(", ")} links no issue.`,
|
|
733
|
+
"Open one with `mergestorm issue create --title <problem> --wait`, answer the Vortex review until it is approved,",
|
|
734
|
+
"then add `Fixes #N` to the tip commit message and submit again.",
|
|
735
|
+
].join("\n"), REVIEW_EXIT.failed, "issue_not_approved");
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
const blocking = statuses.filter((status) => status.state !== "approved" && status.state !== "off");
|
|
739
|
+
if (blocking.length > 0)
|
|
740
|
+
throw issueNotApprovedError(blocking);
|
|
741
|
+
}
|
|
683
742
|
export async function cmdStackSubmit(args, deps = {}) {
|
|
684
743
|
const { extend, autoLand, autoReview, autoPatch, autoResolveConflicts, autoFixCi, rest, serverSide, asJson } = parseStackSubmitArgs(args);
|
|
685
744
|
const api = rest ? "rest" : githubApiFromEnv(deps.env ?? process.env);
|
|
@@ -803,6 +862,21 @@ export async function cmdStackSubmit(args, deps = {}) {
|
|
|
803
862
|
for (const plan of plans) {
|
|
804
863
|
existingPrs.set(plan.branch, await opener.findOpen(plan.branch));
|
|
805
864
|
}
|
|
865
|
+
await assertLinkedIssuesApproved({
|
|
866
|
+
cfg: await loadConfigFn(),
|
|
867
|
+
owner,
|
|
868
|
+
repo,
|
|
869
|
+
layers: plans
|
|
870
|
+
.filter((plan) => existingPrs.get(plan.branch) == null)
|
|
871
|
+
.map((plan) => {
|
|
872
|
+
if (!branchExistsFn(plan.branch, cwd)) {
|
|
873
|
+
throw new CommandError(`Stack layer branch missing locally: ${plan.branch}`);
|
|
874
|
+
}
|
|
875
|
+
const message = tipCommitMessageFn(plan.branch, cwd);
|
|
876
|
+
return { branch: plan.branch, texts: [message, buildPrBodyFn(message)] };
|
|
877
|
+
}),
|
|
878
|
+
warn: progress,
|
|
879
|
+
}, deps);
|
|
806
880
|
const newHeads = plans
|
|
807
881
|
.filter((plan) => existingPrs.get(plan.branch) == null)
|
|
808
882
|
.map((plan) => plan.branch);
|
package/dist/commands/whoami.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { getMe } from "../api.js";
|
|
2
|
-
import { apiBase, configPath, loadConfig, resolveApiKey } from "../config.js";
|
|
1
|
+
import { accountLabel, getMe } from "../api.js";
|
|
2
|
+
import { apiBase, configPath, listAccounts, loadConfig, resolveApiKey, settleAccountName } from "../config.js";
|
|
3
3
|
import { CommandError } from "../errors.js";
|
|
4
4
|
import { ansi } from "../ui/ansi.js";
|
|
5
5
|
import { present } from "../ui/present.js";
|
|
6
|
-
import { canBrowse, openTabsBrowser } from "./browse.js";
|
|
7
6
|
export async function cmdWhoami(args, opts = {}) {
|
|
8
7
|
const asJson = args.includes("--json");
|
|
9
8
|
const cfg = await loadConfig();
|
|
@@ -11,15 +10,17 @@ export async function cmdWhoami(args, opts = {}) {
|
|
|
11
10
|
if (!key) {
|
|
12
11
|
throw new CommandError("Not logged in. Run `mergestorm login` (agents: `mergestorm login --start`, then `--finish`).");
|
|
13
12
|
}
|
|
14
|
-
if (!asJson && canBrowse()) {
|
|
15
|
-
await openTabsBrowser("status");
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
13
|
const me = await getMe(cfg);
|
|
19
14
|
if (!me) {
|
|
20
15
|
throw new CommandError("Live account details unavailable. Could not verify account with /me.");
|
|
21
16
|
}
|
|
17
|
+
const account = (await settleAccountName(cfg, me)) ?? accountLabel(me.account);
|
|
18
|
+
const accounts = (await listAccounts()).map((a) => a.name);
|
|
22
19
|
const payload = {
|
|
20
|
+
account,
|
|
21
|
+
accounts,
|
|
22
|
+
github_login: me.account?.github_login ?? null,
|
|
23
|
+
email: me.account?.email ?? null,
|
|
23
24
|
key_prefix: me.key.prefix,
|
|
24
25
|
key_name: me.key.name ?? null,
|
|
25
26
|
plan_key: me.plan_key ?? null,
|
|
@@ -37,9 +38,12 @@ export async function cmdWhoami(args, opts = {}) {
|
|
|
37
38
|
console.log(text);
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
40
|
-
const lines = [
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
const lines = [` Account ${account ? ansi.bold(account) : "unknown (API too old to say)"}`];
|
|
42
|
+
lines.push(` Key ${ansi.bold(String(payload.key_prefix))}${payload.key_name ? ` (${payload.key_name})` : ""}`);
|
|
43
|
+
const others = accounts.filter((name) => name !== account);
|
|
44
|
+
if (others.length > 0) {
|
|
45
|
+
lines.push(` Others ${others.join(", ")} ${ansi.dim("· mergestorm account use <name>")}`);
|
|
46
|
+
}
|
|
43
47
|
if (payload.plan_key) {
|
|
44
48
|
lines.push(` Plan ${payload.plan_label_key ?? payload.plan_key}`);
|
|
45
49
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,16 +1,69 @@
|
|
|
1
1
|
export declare const DEFAULT_API = "https://api.mergestorm.ai";
|
|
2
|
+
export declare const ACCOUNT_LIMIT = 3;
|
|
2
3
|
export type Config = {
|
|
3
4
|
apiKey?: string;
|
|
4
5
|
apiBase?: string;
|
|
5
6
|
ignoreEnv?: boolean;
|
|
7
|
+
account?: string;
|
|
8
|
+
};
|
|
9
|
+
export type StoredAccount = {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
apiBase?: string;
|
|
12
|
+
};
|
|
13
|
+
export type AccountStore = {
|
|
14
|
+
accounts: Record<string, StoredAccount>;
|
|
15
|
+
activeAccount?: string;
|
|
16
|
+
apiBase?: string;
|
|
17
|
+
ignoreEnv?: boolean;
|
|
18
|
+
};
|
|
19
|
+
type StoreFile = AccountStore & {
|
|
20
|
+
apiKey?: string;
|
|
21
|
+
};
|
|
22
|
+
export type AccountSummary = {
|
|
23
|
+
name: string;
|
|
24
|
+
active: boolean;
|
|
25
|
+
keyPrefix: string;
|
|
26
|
+
apiBase: string;
|
|
27
|
+
};
|
|
28
|
+
export type NamedMe = {
|
|
29
|
+
account?: {
|
|
30
|
+
github_login?: string | null;
|
|
31
|
+
email?: string | null;
|
|
32
|
+
} | null;
|
|
6
33
|
};
|
|
7
34
|
export declare function mergestormHome(env?: NodeJS.ProcessEnv): string;
|
|
8
35
|
export declare function configPath(): string;
|
|
36
|
+
export declare function provisionalAccountName(apiKey: string): string;
|
|
37
|
+
export declare function accountNameFromMe(me: NamedMe | null | undefined): string | null;
|
|
38
|
+
export declare function serializeStore(store: AccountStore): StoreFile;
|
|
39
|
+
export declare function migrateStore(raw: unknown): {
|
|
40
|
+
store: AccountStore;
|
|
41
|
+
migrated: boolean;
|
|
42
|
+
};
|
|
43
|
+
export declare function writeStore(store: AccountStore): Promise<void>;
|
|
44
|
+
export declare function readStore(): Promise<AccountStore>;
|
|
45
|
+
export declare function withAccount<T>(name: string | undefined, fn: () => Promise<T>): Promise<T>;
|
|
46
|
+
export declare function requestedAccount(store: AccountStore, env?: NodeJS.ProcessEnv): string | undefined;
|
|
47
|
+
export declare function selectAccountName(store: AccountStore, requested: string | undefined): string | undefined;
|
|
48
|
+
export declare function configFor(store: AccountStore, name: string | undefined): Config;
|
|
9
49
|
export declare function loadConfig(): Promise<Config>;
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
50
|
+
export declare function accountLimitMessage(store: AccountStore): string;
|
|
51
|
+
export declare function saveAccount(name: string, account: StoredAccount, opts?: {
|
|
52
|
+
activate?: boolean;
|
|
53
|
+
}): Promise<AccountStore>;
|
|
54
|
+
export declare function useAccount(name: string): Promise<AccountStore>;
|
|
55
|
+
export declare function removeAccount(name: string): Promise<AccountStore>;
|
|
56
|
+
export declare function renameAccount(from: string, to: string): Promise<AccountStore>;
|
|
57
|
+
export declare function summarizeAccounts(store: AccountStore): AccountSummary[];
|
|
58
|
+
export declare function listAccounts(): Promise<AccountSummary[]>;
|
|
59
|
+
export declare function settleAccountName(cfg: Config, me: NamedMe | null | undefined): Promise<string | undefined>;
|
|
60
|
+
export declare function splitAccountFlag(args: readonly string[]): {
|
|
61
|
+
account?: string;
|
|
62
|
+
args: string[];
|
|
63
|
+
};
|
|
12
64
|
export declare function apiBase(cfg: Config): string;
|
|
13
65
|
export declare function resolveChatId(cfg: Config): string | undefined;
|
|
14
66
|
export declare function resolveApiKey(cfg: Config): string | undefined;
|
|
15
67
|
/** Short display form of a stored key (prefix only). */
|
|
16
68
|
export declare function keyDisplay(key: string | undefined): string | null;
|
|
69
|
+
export {};
|