@bankr/cli 0.3.37 → 0.3.43
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 +51 -156
- package/dist/cli.js +162 -150
- package/dist/commands/fees.js +17 -7
- package/dist/commands/llm.js +64 -0
- package/dist/commands/login.d.ts +75 -0
- package/dist/commands/login.js +321 -60
- package/dist/commands/{profile.d.ts → project.d.ts} +6 -6
- package/dist/commands/{profile.js → project.js} +65 -65
- package/dist/commands/prompt.d.ts +11 -0
- package/dist/commands/prompt.js +20 -11
- package/dist/commands/status.d.ts +5 -1
- package/dist/commands/status.js +54 -5
- package/dist/commands/update.js +2 -3
- package/dist/commands/x402.js +2 -2
- package/dist/lib/api.d.ts +29 -8
- package/dist/lib/api.js +26 -12
- package/dist/lib/config.d.ts +2 -1
- package/dist/lib/config.js +18 -2
- package/dist/lib/output.d.ts +2 -0
- package/dist/lib/output.js +4 -0
- package/dist/lib/statusUpdates.d.ts +14 -0
- package/dist/lib/statusUpdates.js +38 -0
- package/package.json +1 -1
|
@@ -1,61 +1,61 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { input, confirm, select } from "@inquirer/prompts";
|
|
3
|
-
import {
|
|
3
|
+
import { getOwnProjects, createProject, updateProject, deleteProject, addProjectUpdate, } from "../lib/api.js";
|
|
4
4
|
import * as output from "../lib/output.js";
|
|
5
5
|
import { getErrorMessage } from "../lib/errors.js";
|
|
6
6
|
const BRAND = chalk.hex("#FF613D");
|
|
7
7
|
const DIM = chalk.dim;
|
|
8
|
-
function
|
|
8
|
+
function printProject(project, json) {
|
|
9
9
|
if (json) {
|
|
10
|
-
console.log(JSON.stringify(
|
|
10
|
+
console.log(JSON.stringify(project, null, 2));
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
console.log();
|
|
14
|
-
console.log(` ${BRAND.bold(
|
|
15
|
-
console.log(` ${DIM("slug:")} ${
|
|
16
|
-
console.log(` ${DIM("approved:")} ${
|
|
17
|
-
if (
|
|
18
|
-
console.log(` ${DIM("description:")} ${
|
|
14
|
+
console.log(` ${BRAND.bold(project.projectName)}`);
|
|
15
|
+
console.log(` ${DIM("slug:")} ${project.slug}`);
|
|
16
|
+
console.log(` ${DIM("approved:")} ${project.approved ? chalk.green("yes") : chalk.yellow("no")}`);
|
|
17
|
+
if (project.description) {
|
|
18
|
+
console.log(` ${DIM("description:")} ${project.description}`);
|
|
19
19
|
}
|
|
20
|
-
if (
|
|
21
|
-
console.log(` ${DIM("token:")} $${
|
|
20
|
+
if (project.tokenSymbol) {
|
|
21
|
+
console.log(` ${DIM("token:")} $${project.tokenSymbol} (${project.tokenAddress})`);
|
|
22
22
|
}
|
|
23
|
-
if (
|
|
24
|
-
console.log(` ${DIM("market cap:")} $${
|
|
23
|
+
if (project.marketCapUsd) {
|
|
24
|
+
console.log(` ${DIM("market cap:")} $${project.marketCapUsd.toFixed(0)}`);
|
|
25
25
|
}
|
|
26
|
-
if (
|
|
27
|
-
console.log(` ${DIM("weekly revenue:")} ${
|
|
26
|
+
if (project.weeklyRevenueWeth) {
|
|
27
|
+
console.log(` ${DIM("weekly revenue:")} ${project.weeklyRevenueWeth} WETH`);
|
|
28
28
|
}
|
|
29
|
-
if (
|
|
30
|
-
console.log(` ${DIM("twitter:")} @${
|
|
29
|
+
if (project.twitterUsername) {
|
|
30
|
+
console.log(` ${DIM("twitter:")} @${project.twitterUsername}`);
|
|
31
31
|
}
|
|
32
|
-
if (
|
|
33
|
-
console.log(` ${DIM("website:")} ${
|
|
32
|
+
if (project.website) {
|
|
33
|
+
console.log(` ${DIM("website:")} ${project.website}`);
|
|
34
34
|
}
|
|
35
|
-
if (
|
|
36
|
-
console.log(` ${DIM("team:")} ${
|
|
35
|
+
if (project.teamMembers.length > 0) {
|
|
36
|
+
console.log(` ${DIM("team:")} ${project.teamMembers.length} members`);
|
|
37
37
|
}
|
|
38
|
-
if (
|
|
39
|
-
console.log(` ${DIM("products:")} ${
|
|
38
|
+
if (project.products.length > 0) {
|
|
39
|
+
console.log(` ${DIM("products:")} ${project.products.length}`);
|
|
40
40
|
}
|
|
41
|
-
if (
|
|
42
|
-
console.log(` ${DIM("updates:")} ${
|
|
41
|
+
if (project.projectUpdates.length > 0) {
|
|
42
|
+
console.log(` ${DIM("updates:")} ${project.projectUpdates.length}`);
|
|
43
43
|
}
|
|
44
44
|
console.log();
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
|
-
* Resolve which
|
|
48
|
-
* If --slug is provided, use it. Otherwise, if there's exactly one
|
|
49
|
-
* If multiple
|
|
47
|
+
* Resolve which project to operate on.
|
|
48
|
+
* If --slug is provided, use it. Otherwise, if there's exactly one project, use that.
|
|
49
|
+
* If multiple projects exist, prompt the user to pick.
|
|
50
50
|
*/
|
|
51
|
-
async function resolveSlug(
|
|
51
|
+
async function resolveSlug(projects, slugOpt) {
|
|
52
52
|
if (slugOpt)
|
|
53
53
|
return slugOpt;
|
|
54
|
-
if (
|
|
55
|
-
return
|
|
54
|
+
if (projects.length === 1)
|
|
55
|
+
return projects[0].slug;
|
|
56
56
|
const choice = await select({
|
|
57
57
|
message: "Which project?",
|
|
58
|
-
choices:
|
|
58
|
+
choices: projects.map((p) => ({
|
|
59
59
|
name: `${p.projectName} (${p.slug})`,
|
|
60
60
|
value: p.slug,
|
|
61
61
|
})),
|
|
@@ -63,28 +63,28 @@ async function resolveSlug(profiles, slugOpt) {
|
|
|
63
63
|
});
|
|
64
64
|
return choice;
|
|
65
65
|
}
|
|
66
|
-
export async function
|
|
66
|
+
export async function projectViewCommand(opts) {
|
|
67
67
|
try {
|
|
68
|
-
const
|
|
69
|
-
if (!
|
|
70
|
-
output.info("No
|
|
68
|
+
const projects = await getOwnProjects();
|
|
69
|
+
if (!projects.length) {
|
|
70
|
+
output.info("No projects found. Create one with: bankr project create");
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
|
-
for (const
|
|
74
|
-
|
|
73
|
+
for (const project of projects) {
|
|
74
|
+
printProject(project, !!opts.json);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
catch (err) {
|
|
78
78
|
const msg = getErrorMessage(err);
|
|
79
79
|
if (msg.includes("404")) {
|
|
80
|
-
output.info("No
|
|
80
|
+
output.info("No projects found. Create one with: bankr project create");
|
|
81
81
|
}
|
|
82
82
|
else {
|
|
83
83
|
output.error(msg);
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
export async function
|
|
87
|
+
export async function projectCreateCommand(opts) {
|
|
88
88
|
try {
|
|
89
89
|
let projectName = opts.name;
|
|
90
90
|
if (!projectName) {
|
|
@@ -128,15 +128,15 @@ export async function profileCreateCommand(opts) {
|
|
|
128
128
|
if (website)
|
|
129
129
|
data.website = website;
|
|
130
130
|
}
|
|
131
|
-
const
|
|
132
|
-
output.success("
|
|
133
|
-
|
|
131
|
+
const project = await createProject(data);
|
|
132
|
+
output.success("Project created!");
|
|
133
|
+
printProject(project, !!opts.json);
|
|
134
134
|
}
|
|
135
135
|
catch (err) {
|
|
136
136
|
output.error(getErrorMessage(err));
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
-
export async function
|
|
139
|
+
export async function projectUpdateCommand(opts) {
|
|
140
140
|
try {
|
|
141
141
|
const data = {};
|
|
142
142
|
if (opts.name)
|
|
@@ -153,28 +153,28 @@ export async function profileUpdateCommand(opts) {
|
|
|
153
153
|
output.error("No fields to update. Use flags: --name, --description, --token, --image, --website");
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
|
-
const
|
|
157
|
-
if (!
|
|
158
|
-
output.error("No
|
|
156
|
+
const projects = await getOwnProjects();
|
|
157
|
+
if (!projects.length) {
|
|
158
|
+
output.error("No projects found. Create one first with: bankr project create");
|
|
159
159
|
return;
|
|
160
160
|
}
|
|
161
|
-
const slug = await resolveSlug(
|
|
162
|
-
const
|
|
163
|
-
output.success("
|
|
164
|
-
|
|
161
|
+
const slug = await resolveSlug(projects, opts.slug);
|
|
162
|
+
const project = await updateProject(slug, data);
|
|
163
|
+
output.success("Project updated!");
|
|
164
|
+
printProject(project, !!opts.json);
|
|
165
165
|
}
|
|
166
166
|
catch (err) {
|
|
167
167
|
output.error(getErrorMessage(err));
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
-
export async function
|
|
170
|
+
export async function projectDeleteCommand(opts) {
|
|
171
171
|
try {
|
|
172
|
-
const
|
|
173
|
-
if (!
|
|
174
|
-
output.error("No
|
|
172
|
+
const projects = await getOwnProjects();
|
|
173
|
+
if (!projects.length) {
|
|
174
|
+
output.error("No projects found.");
|
|
175
175
|
return;
|
|
176
176
|
}
|
|
177
|
-
const slug = await resolveSlug(
|
|
177
|
+
const slug = await resolveSlug(projects, opts.slug);
|
|
178
178
|
const yes = await confirm({
|
|
179
179
|
message: `Are you sure you want to delete "${slug}"?`,
|
|
180
180
|
default: false,
|
|
@@ -184,14 +184,14 @@ export async function profileDeleteCommand(opts) {
|
|
|
184
184
|
output.info("Cancelled.");
|
|
185
185
|
return;
|
|
186
186
|
}
|
|
187
|
-
await
|
|
188
|
-
output.success("
|
|
187
|
+
await deleteProject(slug);
|
|
188
|
+
output.success("Project deleted.");
|
|
189
189
|
}
|
|
190
190
|
catch (err) {
|
|
191
191
|
output.error(getErrorMessage(err));
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
export async function
|
|
194
|
+
export async function projectAddUpdateCommand(opts) {
|
|
195
195
|
try {
|
|
196
196
|
let title = opts.title;
|
|
197
197
|
let content = opts.content;
|
|
@@ -209,20 +209,20 @@ export async function profileAddUpdateCommand(opts) {
|
|
|
209
209
|
required: true,
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
|
-
const
|
|
213
|
-
if (!
|
|
214
|
-
output.error("No
|
|
212
|
+
const projects = await getOwnProjects();
|
|
213
|
+
if (!projects.length) {
|
|
214
|
+
output.error("No projects found. Create one first with: bankr project create");
|
|
215
215
|
return;
|
|
216
216
|
}
|
|
217
|
-
const slug = await resolveSlug(
|
|
218
|
-
const
|
|
217
|
+
const slug = await resolveSlug(projects, opts.slug);
|
|
218
|
+
const project = await addProjectUpdate(slug, { title, content });
|
|
219
219
|
output.success("Project update added!");
|
|
220
220
|
if (opts.json) {
|
|
221
|
-
console.log(JSON.stringify(
|
|
221
|
+
console.log(JSON.stringify(project, null, 2));
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
catch (err) {
|
|
225
225
|
output.error(getErrorMessage(err));
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
|
-
//# sourceMappingURL=
|
|
228
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/** Valid Max Mode model IDs — hardcoded because CLI is standalone (no monorepo imports).
|
|
2
|
+
* Must be manually kept in sync with models in the LLM gateway DB.
|
|
3
|
+
*
|
|
4
|
+
* Only the two newest releases of each vendor tier are listed, and only the
|
|
5
|
+
* frontier / flagship / balanced ranks — matching what the web picker shows.
|
|
6
|
+
* Older generations and `light` lines still run on the gateway, but the CLI
|
|
7
|
+
* stops steering people onto them. Superseding a model here means DROPPING
|
|
8
|
+
* the one it pushes out of the tier, not just adding the new id. */
|
|
9
|
+
export declare const VALID_MAX_MODE_MODELS: Set<string>;
|
|
10
|
+
/** The `-m, --model` help example; prompt.test.ts fails if the set drops it. */
|
|
11
|
+
export declare const MAX_MODE_MODEL_EXAMPLE = "claude-opus-5.5";
|
|
1
12
|
export interface PromptOptions {
|
|
2
13
|
thread?: string;
|
|
3
14
|
continue?: boolean;
|
package/dist/commands/prompt.js
CHANGED
|
@@ -3,6 +3,7 @@ import { emitCESP } from "../lib/cesp/engine.js";
|
|
|
3
3
|
import { getLastThreadId, requireApiKey, setLastThreadId, } from "../lib/config.js";
|
|
4
4
|
import * as output from "../lib/output.js";
|
|
5
5
|
import { getErrorMessage } from "../lib/errors.js";
|
|
6
|
+
import { createStatusTrail } from "../lib/statusUpdates.js";
|
|
6
7
|
/** Valid Max Mode model IDs — hardcoded because CLI is standalone (no monorepo imports).
|
|
7
8
|
* Must be manually kept in sync with models in the LLM gateway DB.
|
|
8
9
|
*
|
|
@@ -11,31 +12,32 @@ import { getErrorMessage } from "../lib/errors.js";
|
|
|
11
12
|
* Older generations and `light` lines still run on the gateway, but the CLI
|
|
12
13
|
* stops steering people onto them. Superseding a model here means DROPPING
|
|
13
14
|
* the one it pushes out of the tier, not just adding the new id. */
|
|
14
|
-
const VALID_MAX_MODE_MODELS = new Set([
|
|
15
|
+
export const VALID_MAX_MODE_MODELS = new Set([
|
|
15
16
|
// Claude (Vertex AI)
|
|
16
17
|
"claude-fable-5.1",
|
|
17
18
|
"claude-fable-5",
|
|
19
|
+
"claude-opus-5.5",
|
|
18
20
|
"claude-opus-5",
|
|
19
|
-
"claude-
|
|
21
|
+
"claude-sonnet-5.5",
|
|
20
22
|
"claude-sonnet-5",
|
|
21
|
-
"claude-sonnet-4.6",
|
|
22
23
|
// Gemini (Vertex AI) — gemini-3-pro deliberately absent: removed 2026-03-09,
|
|
23
24
|
// both provider slugs retired. The Flash Lite tier likewise: 3.5 and 3.1
|
|
24
|
-
// deprecated 2026-09-09 (replaced by gemini-3.8-flash).
|
|
25
|
-
//
|
|
25
|
+
// deprecated 2026-09-09 (replaced by gemini-3.8-flash). gemini-2.5-pro too,
|
|
26
|
+
// as of 2026-09-19: Google retires the whole 2.5 line on 2026-10-20, so the
|
|
27
|
+
// `gemini-pro` tier shows only 3.1 Pro. Don't re-add on a sync pass.
|
|
26
28
|
"gemini-3.8-flash",
|
|
27
29
|
"gemini-3.7-flash",
|
|
28
30
|
"gemini-3.1-pro",
|
|
29
|
-
"gemini-2.5-pro",
|
|
30
31
|
// OpenAI (OpenRouter)
|
|
31
32
|
"gpt-6-astra",
|
|
33
|
+
"gpt-6-sol",
|
|
32
34
|
"gpt-5.6-sol",
|
|
33
|
-
"gpt-5.5",
|
|
34
35
|
"gpt-5.6-terra",
|
|
36
|
+
"gpt-5.4-mini",
|
|
35
37
|
"gpt-5.2-codex",
|
|
36
38
|
// Grok (OpenRouter)
|
|
39
|
+
"grok-4.7",
|
|
37
40
|
"grok-4.6",
|
|
38
|
-
"grok-4.5",
|
|
39
41
|
// DeepSeek (OpenRouter) — v4.1-flash is its own tier at `balanced`
|
|
40
42
|
// ($0.30/$1.20, 3.3x under the V4 Pro card), not the `light` flash line.
|
|
41
43
|
"deepseek-v4-pro-0813",
|
|
@@ -56,8 +58,11 @@ const VALID_MAX_MODE_MODELS = new Set([
|
|
|
56
58
|
"kimi-k2.6",
|
|
57
59
|
"glm-5.2",
|
|
58
60
|
"glm-5.3",
|
|
61
|
+
"glm-5.3-flashx",
|
|
59
62
|
"glm-5-turbo",
|
|
60
63
|
]);
|
|
64
|
+
/** The `-m, --model` help example; prompt.test.ts fails if the set drops it. */
|
|
65
|
+
export const MAX_MODE_MODEL_EXAMPLE = "claude-opus-5.5";
|
|
61
66
|
export async function promptCommand(text, options = {}) {
|
|
62
67
|
requireApiKey();
|
|
63
68
|
// Resolve thread ID from flags
|
|
@@ -114,11 +119,15 @@ export async function promptCommand(text, options = {}) {
|
|
|
114
119
|
}
|
|
115
120
|
try {
|
|
116
121
|
const startTime = Date.now();
|
|
122
|
+
// ora writes to stderr, so a piped consumer still gets only the final
|
|
123
|
+
// response on stdout.
|
|
124
|
+
const renderTrail = createStatusTrail(spin);
|
|
117
125
|
const result = await pollJob(jobId, {
|
|
118
126
|
interval: 2000,
|
|
119
|
-
onStatus: () => {
|
|
120
|
-
|
|
121
|
-
spin.text = `Processing... (${
|
|
127
|
+
onStatus: (job) => {
|
|
128
|
+
// Set the text first so the restarted spinner shows the current elapsed.
|
|
129
|
+
spin.text = `Processing... (${output.formatDuration(Date.now() - startTime)})`;
|
|
130
|
+
renderTrail(job.statusUpdates);
|
|
122
131
|
},
|
|
123
132
|
});
|
|
124
133
|
// Save thread ID from the final result (or from initial response)
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface StatusOptions {
|
|
2
|
+
/** Poll until the job reaches a terminal state, streaming progress as it arrives. */
|
|
3
|
+
wait?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare function statusCommand(jobId: string, options?: StatusOptions): Promise<void>;
|
|
2
6
|
//# sourceMappingURL=status.d.ts.map
|
package/dist/commands/status.js
CHANGED
|
@@ -1,12 +1,49 @@
|
|
|
1
|
-
import { getJobStatus } from "../lib/api.js";
|
|
1
|
+
import { getJobStatus, pollJob, PollTimeoutError, } from "../lib/api.js";
|
|
2
2
|
import { requireApiKey } from "../lib/config.js";
|
|
3
3
|
import * as output from "../lib/output.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { createStatusTrail, newStatusMessages } from "../lib/statusUpdates.js";
|
|
5
|
+
/**
|
|
6
|
+
* Follows a running job, streaming its progress above `spin`. `--wait` attaches
|
|
7
|
+
* to a job that may already be minutes old, so running out the poll budget is a
|
|
8
|
+
* normal outcome: report the last state seen rather than failing the command.
|
|
9
|
+
*/
|
|
10
|
+
async function followJob(jobId, spin) {
|
|
11
|
+
const startTime = Date.now();
|
|
12
|
+
const renderTrail = createStatusTrail(spin);
|
|
13
|
+
let lastSeen;
|
|
14
|
+
const elapsed = () => output.formatDuration(Date.now() - startTime);
|
|
7
15
|
try {
|
|
8
|
-
const status = await
|
|
16
|
+
const status = await pollJob(jobId, {
|
|
17
|
+
interval: 2000,
|
|
18
|
+
onStatus: (job) => {
|
|
19
|
+
lastSeen = job;
|
|
20
|
+
// Set the text first so the restarted spinner shows the current elapsed.
|
|
21
|
+
spin.text = `Waiting for job... (${elapsed()})`;
|
|
22
|
+
renderTrail(job.statusUpdates);
|
|
23
|
+
},
|
|
24
|
+
});
|
|
9
25
|
spin.stop();
|
|
26
|
+
return status;
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (!(err instanceof PollTimeoutError) || !lastSeen)
|
|
30
|
+
throw err;
|
|
31
|
+
spin.warn(`Still running after ${elapsed()}; re-run to keep following`);
|
|
32
|
+
return lastSeen;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function statusCommand(jobId, options = {}) {
|
|
36
|
+
requireApiKey();
|
|
37
|
+
const spin = output.spinner(options.wait ? "Waiting for job..." : "Fetching job status...");
|
|
38
|
+
try {
|
|
39
|
+
let status;
|
|
40
|
+
if (options.wait) {
|
|
41
|
+
status = await followJob(jobId, spin);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
status = await getJobStatus(jobId);
|
|
45
|
+
spin.stop();
|
|
46
|
+
}
|
|
10
47
|
output.label("Job", status.jobId);
|
|
11
48
|
output.label("Status", output.formatStatus(status.status));
|
|
12
49
|
output.label("Prompt", `"${status.prompt}"`);
|
|
@@ -23,6 +60,18 @@ export async function statusCommand(jobId) {
|
|
|
23
60
|
if (status.processingTime) {
|
|
24
61
|
output.label("Duration", output.formatDuration(status.processingTime));
|
|
25
62
|
}
|
|
63
|
+
// With --wait the trail already streamed above the spinner; reprinting it
|
|
64
|
+
// here would show every line twice.
|
|
65
|
+
const progress = options.wait
|
|
66
|
+
? []
|
|
67
|
+
: newStatusMessages(status.statusUpdates, 0);
|
|
68
|
+
if (progress.length) {
|
|
69
|
+
output.blank();
|
|
70
|
+
output.brandBold("Progress:");
|
|
71
|
+
for (const message of progress) {
|
|
72
|
+
output.dim(` · ${message}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
26
75
|
if (status.response) {
|
|
27
76
|
console.log();
|
|
28
77
|
console.log(status.response);
|
package/dist/commands/update.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
1
|
import { execSync } from "node:child_process";
|
|
3
2
|
import * as output from "../lib/output.js";
|
|
4
3
|
import { getErrorMessage } from "../lib/errors.js";
|
|
4
|
+
import { CLI_VERSION } from "../lib/config.js";
|
|
5
5
|
const PACKAGE_NAME = "@bankr/cli";
|
|
6
6
|
/**
|
|
7
7
|
* Compare two semver version strings.
|
|
@@ -31,8 +31,7 @@ async function fetchLatestVersion() {
|
|
|
31
31
|
return data.version;
|
|
32
32
|
}
|
|
33
33
|
function getCurrentVersion() {
|
|
34
|
-
|
|
35
|
-
return pkg.version;
|
|
34
|
+
return CLI_VERSION;
|
|
36
35
|
}
|
|
37
36
|
/**
|
|
38
37
|
* Detect which package manager installed the CLI globally.
|
package/dist/commands/x402.js
CHANGED
|
@@ -869,7 +869,7 @@ async function fetchSchemaForInteractive(url) {
|
|
|
869
869
|
// Strategy 2: Discover API (already deployed, searches by service name)
|
|
870
870
|
if (isBankr && parts.length >= 2) {
|
|
871
871
|
try {
|
|
872
|
-
const serviceName = parts
|
|
872
|
+
const serviceName = parts.at(-1);
|
|
873
873
|
const discoverRes = await fetch(`${getApiUrl()}/x402/endpoints/discover?${new URLSearchParams({ q: serviceName, limit: "5" })}`);
|
|
874
874
|
if (discoverRes.ok) {
|
|
875
875
|
const discoverData = (await discoverRes.json());
|
|
@@ -931,7 +931,7 @@ async function fetchSchemaForInteractive(url) {
|
|
|
931
931
|
const amountAtomic = BigInt(acceptAmount);
|
|
932
932
|
const amountUsd = Number(amountAtomic) / 1000000;
|
|
933
933
|
// Extract service name from URL path
|
|
934
|
-
const serviceName = parts
|
|
934
|
+
const serviceName = parts.at(-1) ?? "endpoint";
|
|
935
935
|
return {
|
|
936
936
|
name: serviceName,
|
|
937
937
|
description: accept?.description ?? "",
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -26,6 +26,12 @@ export interface PromptResponse {
|
|
|
26
26
|
status: string;
|
|
27
27
|
message: string;
|
|
28
28
|
}
|
|
29
|
+
/** One agent progress line, as the API stores it on the job. */
|
|
30
|
+
export interface JobStatusUpdate {
|
|
31
|
+
message: string;
|
|
32
|
+
/** ISO 8601 — a Date on the server, serialized over the wire. */
|
|
33
|
+
timestamp: string;
|
|
34
|
+
}
|
|
29
35
|
export interface JobStatusResponse {
|
|
30
36
|
success: boolean;
|
|
31
37
|
jobId: string;
|
|
@@ -34,6 +40,8 @@ export interface JobStatusResponse {
|
|
|
34
40
|
prompt: string;
|
|
35
41
|
createdAt: string;
|
|
36
42
|
processingTime?: number;
|
|
43
|
+
/** Progress the agent emitted during the run; grows as the job advances. */
|
|
44
|
+
statusUpdates?: JobStatusUpdate[];
|
|
37
45
|
response?: string;
|
|
38
46
|
error?: string;
|
|
39
47
|
startedAt?: string;
|
|
@@ -66,6 +74,11 @@ export declare function submitPrompt(prompt: string, threadId?: string, maxMode?
|
|
|
66
74
|
}): Promise<PromptResponse>;
|
|
67
75
|
export declare function getJobStatus(jobId: string): Promise<JobStatusResponse>;
|
|
68
76
|
export declare function cancelJob(jobId: string): Promise<JobStatusResponse>;
|
|
77
|
+
/**
|
|
78
|
+
* Answers "can this key read the account", not "is the API up": `/wallet/me`
|
|
79
|
+
* is key-authenticated, so invalid/revoked/IP-blocked keys (401/403), keys with
|
|
80
|
+
* no active wallet (401/404/banned/suspended) and API errors all yield false.
|
|
81
|
+
*/
|
|
69
82
|
export declare function validateApiKey(): Promise<boolean>;
|
|
70
83
|
export declare function getUserInfo(): Promise<UserInfoResponse>;
|
|
71
84
|
export interface TokenBalanceInfo {
|
|
@@ -132,6 +145,14 @@ export declare function getPortfolio(opts?: PortfolioOptions): Promise<Portfolio
|
|
|
132
145
|
export type BalancesResponse = PortfolioResponse;
|
|
133
146
|
/** @deprecated Use getPortfolio instead */
|
|
134
147
|
export declare const getBalances: (chains?: string[], showLowValueTokens?: boolean) => Promise<PortfolioResponse>;
|
|
148
|
+
/**
|
|
149
|
+
* The wait ran out, not the job — every fetch succeeded and the job is still
|
|
150
|
+
* running. Typed so callers can tell it apart from a real request failure.
|
|
151
|
+
*/
|
|
152
|
+
export declare class PollTimeoutError extends Error {
|
|
153
|
+
readonly attempts: number;
|
|
154
|
+
constructor(attempts: number);
|
|
155
|
+
}
|
|
135
156
|
export declare function pollJob(jobId: string, opts?: {
|
|
136
157
|
interval?: number;
|
|
137
158
|
maxAttempts?: number;
|
|
@@ -406,7 +427,7 @@ export interface BuildClaimResponse {
|
|
|
406
427
|
* Unauthenticated -- calls the public endpoint. The CLI signs and
|
|
407
428
|
* broadcasts locally.
|
|
408
429
|
*/
|
|
409
|
-
export interface
|
|
430
|
+
export interface ProjectResponse {
|
|
410
431
|
id: string;
|
|
411
432
|
slug: string;
|
|
412
433
|
projectName: string;
|
|
@@ -447,18 +468,18 @@ export interface AgentProfileResponse {
|
|
|
447
468
|
isPublished?: boolean;
|
|
448
469
|
createdAt: string;
|
|
449
470
|
}
|
|
450
|
-
export declare function
|
|
451
|
-
/** @deprecated Use
|
|
452
|
-
export declare function
|
|
453
|
-
export declare function
|
|
454
|
-
export declare function
|
|
455
|
-
export declare function
|
|
471
|
+
export declare function getOwnProjects(): Promise<ProjectResponse[]>;
|
|
472
|
+
/** @deprecated Use getOwnProjects() — returns first project for backward compat */
|
|
473
|
+
export declare function getOwnProject(): Promise<ProjectResponse>;
|
|
474
|
+
export declare function createProject(data: Record<string, unknown>): Promise<ProjectResponse>;
|
|
475
|
+
export declare function updateProject(slug: string, data: Record<string, unknown>): Promise<ProjectResponse>;
|
|
476
|
+
export declare function deleteProject(slug: string): Promise<{
|
|
456
477
|
success: boolean;
|
|
457
478
|
}>;
|
|
458
479
|
export declare function addProjectUpdate(slug: string, data: {
|
|
459
480
|
title: string;
|
|
460
481
|
content: string;
|
|
461
|
-
}): Promise<
|
|
482
|
+
}): Promise<ProjectResponse>;
|
|
462
483
|
export interface TokenSearchResult {
|
|
463
484
|
address: string;
|
|
464
485
|
symbol: string;
|
package/dist/lib/api.js
CHANGED
|
@@ -72,11 +72,14 @@ export async function cancelJob(jobId) {
|
|
|
72
72
|
});
|
|
73
73
|
return handleResponse(res);
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Answers "can this key read the account", not "is the API up": `/wallet/me`
|
|
77
|
+
* is key-authenticated, so invalid/revoked/IP-blocked keys (401/403), keys with
|
|
78
|
+
* no active wallet (401/404/banned/suspended) and API errors all yield false.
|
|
79
|
+
*/
|
|
75
80
|
export async function validateApiKey() {
|
|
76
81
|
try {
|
|
77
|
-
const res = await
|
|
78
|
-
headers: { "X-API-Key": requireApiKey(), "User-Agent": CLI_USER_AGENT },
|
|
79
|
-
});
|
|
82
|
+
const res = await authedFetch(`${getApiUrl()}/wallet/me`);
|
|
80
83
|
return res.ok;
|
|
81
84
|
}
|
|
82
85
|
catch {
|
|
@@ -101,6 +104,17 @@ export async function getPortfolio(opts = {}) {
|
|
|
101
104
|
}
|
|
102
105
|
/** @deprecated Use getPortfolio instead */
|
|
103
106
|
export const getBalances = (chains, showLowValueTokens) => getPortfolio({ chains, showLowValueTokens });
|
|
107
|
+
/**
|
|
108
|
+
* The wait ran out, not the job — every fetch succeeded and the job is still
|
|
109
|
+
* running. Typed so callers can tell it apart from a real request failure.
|
|
110
|
+
*/
|
|
111
|
+
export class PollTimeoutError extends Error {
|
|
112
|
+
constructor(attempts) {
|
|
113
|
+
super(`Polling timed out after ${attempts} attempts`);
|
|
114
|
+
this.attempts = attempts;
|
|
115
|
+
this.name = "PollTimeoutError";
|
|
116
|
+
}
|
|
117
|
+
}
|
|
104
118
|
export async function pollJob(jobId, opts = {}) {
|
|
105
119
|
const { interval = 2000, maxAttempts = 150, onStatus } = opts;
|
|
106
120
|
let attempts = 0;
|
|
@@ -113,7 +127,7 @@ export async function pollJob(jobId, opts = {}) {
|
|
|
113
127
|
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
114
128
|
attempts++;
|
|
115
129
|
}
|
|
116
|
-
throw new
|
|
130
|
+
throw new PollTimeoutError(maxAttempts);
|
|
117
131
|
}
|
|
118
132
|
export async function sign(request) {
|
|
119
133
|
const res = await authedFetch(`${getApiUrl()}/wallet/sign`, {
|
|
@@ -269,30 +283,30 @@ export async function claimTokenLaunchFees(tokenAddress) {
|
|
|
269
283
|
});
|
|
270
284
|
return handleResponse(res);
|
|
271
285
|
}
|
|
272
|
-
export async function
|
|
286
|
+
export async function getOwnProjects() {
|
|
273
287
|
const res = await authedFetch(`${getApiUrl()}/agent/profile?multi=true`);
|
|
274
288
|
return handleResponse(res);
|
|
275
289
|
}
|
|
276
|
-
/** @deprecated Use
|
|
277
|
-
export async function
|
|
278
|
-
const
|
|
279
|
-
return
|
|
290
|
+
/** @deprecated Use getOwnProjects() — returns first project for backward compat */
|
|
291
|
+
export async function getOwnProject() {
|
|
292
|
+
const projects = await getOwnProjects();
|
|
293
|
+
return projects[0];
|
|
280
294
|
}
|
|
281
|
-
export async function
|
|
295
|
+
export async function createProject(data) {
|
|
282
296
|
const res = await authedFetch(`${getApiUrl()}/agent/profile?multi=true`, {
|
|
283
297
|
method: "POST",
|
|
284
298
|
body: JSON.stringify(data),
|
|
285
299
|
});
|
|
286
300
|
return handleResponse(res);
|
|
287
301
|
}
|
|
288
|
-
export async function
|
|
302
|
+
export async function updateProject(slug, data) {
|
|
289
303
|
const res = await authedFetch(`${getApiUrl()}/agent/profile/${encodeURIComponent(slug)}`, {
|
|
290
304
|
method: "PUT",
|
|
291
305
|
body: JSON.stringify(data),
|
|
292
306
|
});
|
|
293
307
|
return handleResponse(res);
|
|
294
308
|
}
|
|
295
|
-
export async function
|
|
309
|
+
export async function deleteProject(slug) {
|
|
296
310
|
const res = await authedFetch(`${getApiUrl()}/agent/profile/${encodeURIComponent(slug)}`, {
|
|
297
311
|
method: "DELETE",
|
|
298
312
|
});
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -11,7 +11,8 @@ export declare function setConfigPath(path: string): void;
|
|
|
11
11
|
export declare function getConfigPath(): string;
|
|
12
12
|
export declare const DEFAULT_API_URL = "https://api.bankr.bot";
|
|
13
13
|
export declare const DEFAULT_LLM_URL = "https://llm.bankr.bot";
|
|
14
|
-
export declare const
|
|
14
|
+
export declare const CLI_VERSION: string;
|
|
15
|
+
export declare const CLI_USER_AGENT: string;
|
|
15
16
|
export declare function readConfig(): BankrConfig;
|
|
16
17
|
export declare function writeConfig(config: BankrConfig): void;
|
|
17
18
|
export declare function clearConfig(): void;
|
package/dist/lib/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync, } from "fs";
|
|
2
|
-
import { homedir } from "os";
|
|
2
|
+
import { homedir, platform, release } from "os";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
4
|
let configPathOverride;
|
|
5
5
|
const DEFAULT_CONFIG_FILE = join(homedir(), ".bankr", "config.json");
|
|
@@ -11,7 +11,23 @@ export function getConfigPath() {
|
|
|
11
11
|
}
|
|
12
12
|
export const DEFAULT_API_URL = "https://api.bankr.bot";
|
|
13
13
|
export const DEFAULT_LLM_URL = "https://llm.bankr.bot";
|
|
14
|
-
export const
|
|
14
|
+
export const CLI_VERSION = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf-8")).version;
|
|
15
|
+
/** Browser-style platform token so the API's shared user-agent parser (which
|
|
16
|
+
* clamps to known families) names the OS on an out-of-band approval screen
|
|
17
|
+
* as "Bankr CLI · macOS". Never the hostname or username. */
|
|
18
|
+
function platformToken() {
|
|
19
|
+
switch (platform()) {
|
|
20
|
+
case "darwin":
|
|
21
|
+
return "Macintosh";
|
|
22
|
+
case "win32":
|
|
23
|
+
return "Windows NT";
|
|
24
|
+
case "linux":
|
|
25
|
+
return "Linux";
|
|
26
|
+
default:
|
|
27
|
+
return platform();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export const CLI_USER_AGENT = `bankr-cli/${CLI_VERSION} (${platformToken()}; ${platform()} ${release()})`;
|
|
15
31
|
function ensureConfigDir() {
|
|
16
32
|
const configDir = dirname(getConfigPath());
|
|
17
33
|
if (!existsSync(configDir)) {
|