@qoren/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/LICENSE +202 -0
- package/README.md +162 -0
- package/dist/args.d.ts +5 -0
- package/dist/args.d.ts.map +1 -0
- package/dist/args.js +23 -0
- package/dist/args.js.map +1 -0
- package/dist/commands/account.d.ts +4 -0
- package/dist/commands/account.d.ts.map +1 -0
- package/dist/commands/account.js +154 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/agent.d.ts +27 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +968 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/api.d.ts +4 -0
- package/dist/commands/api.d.ts.map +1 -0
- package/dist/commands/api.js +66 -0
- package/dist/commands/api.js.map +1 -0
- package/dist/commands/approvals.d.ts +11 -0
- package/dist/commands/approvals.d.ts.map +1 -0
- package/dist/commands/approvals.js +140 -0
- package/dist/commands/approvals.js.map +1 -0
- package/dist/commands/auth.d.ts +4 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +215 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/clients.d.ts +62 -0
- package/dist/commands/clients.d.ts.map +1 -0
- package/dist/commands/clients.js +311 -0
- package/dist/commands/clients.js.map +1 -0
- package/dist/commands/console.d.ts +4 -0
- package/dist/commands/console.d.ts.map +1 -0
- package/dist/commands/console.js +26 -0
- package/dist/commands/console.js.map +1 -0
- package/dist/commands/customAgent.d.ts +42 -0
- package/dist/commands/customAgent.d.ts.map +1 -0
- package/dist/commands/customAgent.js +449 -0
- package/dist/commands/customAgent.js.map +1 -0
- package/dist/commands/designer.d.ts +32 -0
- package/dist/commands/designer.d.ts.map +1 -0
- package/dist/commands/designer.js +682 -0
- package/dist/commands/designer.js.map +1 -0
- package/dist/commands/env.d.ts +15 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +245 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/interactive.d.ts +4 -0
- package/dist/commands/interactive.d.ts.map +1 -0
- package/dist/commands/interactive.js +30 -0
- package/dist/commands/interactive.js.map +1 -0
- package/dist/commands/jobs.d.ts +4 -0
- package/dist/commands/jobs.d.ts.map +1 -0
- package/dist/commands/jobs.js +59 -0
- package/dist/commands/jobs.js.map +1 -0
- package/dist/commands/secrets.d.ts +15 -0
- package/dist/commands/secrets.d.ts.map +1 -0
- package/dist/commands/secrets.js +164 -0
- package/dist/commands/secrets.js.map +1 -0
- package/dist/commands/webhook.d.ts +4 -0
- package/dist/commands/webhook.d.ts.map +1 -0
- package/dist/commands/webhook.js +275 -0
- package/dist/commands/webhook.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +117 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +52 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +163 -0
- package/dist/context.js.map +1 -0
- package/dist/duration.d.ts +9 -0
- package/dist/duration.d.ts.map +1 -0
- package/dist/duration.js +30 -0
- package/dist/duration.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/issues.d.ts +10 -0
- package/dist/issues.d.ts.map +1 -0
- package/dist/issues.js +45 -0
- package/dist/issues.js.map +1 -0
- package/dist/jobProgress.d.ts +12 -0
- package/dist/jobProgress.d.ts.map +1 -0
- package/dist/jobProgress.js +56 -0
- package/dist/jobProgress.js.map +1 -0
- package/dist/loopback.d.ts +28 -0
- package/dist/loopback.d.ts.map +1 -0
- package/dist/loopback.js +110 -0
- package/dist/loopback.js.map +1 -0
- package/dist/migrate/apply.d.ts +29 -0
- package/dist/migrate/apply.d.ts.map +1 -0
- package/dist/migrate/apply.js +135 -0
- package/dist/migrate/apply.js.map +1 -0
- package/dist/migrate/bundle.d.ts +89 -0
- package/dist/migrate/bundle.d.ts.map +1 -0
- package/dist/migrate/bundle.js +681 -0
- package/dist/migrate/bundle.js.map +1 -0
- package/dist/migrate/tar.d.ts +9 -0
- package/dist/migrate/tar.d.ts.map +1 -0
- package/dist/migrate/tar.js +89 -0
- package/dist/migrate/tar.js.map +1 -0
- package/dist/output.d.ts +46 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +152 -0
- package/dist/output.js.map +1 -0
- package/dist/program.d.ts +17 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +89 -0
- package/dist/program.js.map +1 -0
- package/dist/runtimes.d.ts +11 -0
- package/dist/runtimes.d.ts.map +1 -0
- package/dist/runtimes.js +20 -0
- package/dist/runtimes.js.map +1 -0
- package/dist/slug.d.ts +3 -0
- package/dist/slug.d.ts.map +1 -0
- package/dist/slug.js +15 -0
- package/dist/slug.js.map +1 -0
- package/dist/taskChain.d.ts +20 -0
- package/dist/taskChain.d.ts.map +1 -0
- package/dist/taskChain.js +40 -0
- package/dist/taskChain.js.map +1 -0
- package/dist/taskDelivery.d.ts +33 -0
- package/dist/taskDelivery.d.ts.map +1 -0
- package/dist/taskDelivery.js +67 -0
- package/dist/taskDelivery.js.map +1 -0
- package/dist/tui/app.d.ts +5 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +130 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/index.d.ts +12 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +34 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/model.d.ts +110 -0
- package/dist/tui/model.d.ts.map +1 -0
- package/dist/tui/model.js +257 -0
- package/dist/tui/model.js.map +1 -0
- package/dist/tui/overlay.d.ts +66 -0
- package/dist/tui/overlay.d.ts.map +1 -0
- package/dist/tui/overlay.js +216 -0
- package/dist/tui/overlay.js.map +1 -0
- package/dist/tui/panes/account.d.ts +5 -0
- package/dist/tui/panes/account.d.ts.map +1 -0
- package/dist/tui/panes/account.js +108 -0
- package/dist/tui/panes/account.js.map +1 -0
- package/dist/tui/panes/agents.d.ts +9 -0
- package/dist/tui/panes/agents.d.ts.map +1 -0
- package/dist/tui/panes/agents.js +340 -0
- package/dist/tui/panes/agents.js.map +1 -0
- package/dist/tui/panes/chat.d.ts +14 -0
- package/dist/tui/panes/chat.d.ts.map +1 -0
- package/dist/tui/panes/chat.js +169 -0
- package/dist/tui/panes/chat.js.map +1 -0
- package/dist/tui/panes/environments.d.ts +6 -0
- package/dist/tui/panes/environments.d.ts.map +1 -0
- package/dist/tui/panes/environments.js +364 -0
- package/dist/tui/panes/environments.js.map +1 -0
- package/dist/tui/panes/jobs.d.ts +5 -0
- package/dist/tui/panes/jobs.d.ts.map +1 -0
- package/dist/tui/panes/jobs.js +104 -0
- package/dist/tui/panes/jobs.js.map +1 -0
- package/dist/tui/store.d.ts +40 -0
- package/dist/tui/store.d.ts.map +1 -0
- package/dist/tui/store.js +124 -0
- package/dist/tui/store.js.map +1 -0
- package/dist/tui/ui.d.ts +95 -0
- package/dist/tui/ui.d.ts.map +1 -0
- package/dist/tui/ui.js +144 -0
- package/dist/tui/ui.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type AgencyClient, type ClientCosts, type ClientHologramLink, type Machine } from "@qoren/sdk";
|
|
3
|
+
import { type Context, type GlobalOptions } from "../context.js";
|
|
4
|
+
/** The upstream refusal for an account without clients. */
|
|
5
|
+
export declare const CLIENTS_DISABLED = "Clients are not enabled for this account.";
|
|
6
|
+
/**
|
|
7
|
+
* The feature refusal as a plain failure; any other error untouched.
|
|
8
|
+
*
|
|
9
|
+
* A bare 403 exits 3 ("sign in again"), which is the wrong advice here: the
|
|
10
|
+
* credential is fine, the account just does not have the feature. The message
|
|
11
|
+
* is the server's own, so it stays one clean sentence.
|
|
12
|
+
*/
|
|
13
|
+
export declare function clientsGateError(err: unknown): unknown;
|
|
14
|
+
/** Await a gated call, reporting the feature refusal cleanly. */
|
|
15
|
+
export declare function gated<T>(call: Promise<T>): Promise<T>;
|
|
16
|
+
/**
|
|
17
|
+
* Pick one client by id or exact name. Ids win, then active names (unique
|
|
18
|
+
* upstream), then an archived name when only one matches. Pure so the rules
|
|
19
|
+
* are testable without a control plane.
|
|
20
|
+
*/
|
|
21
|
+
export declare function matchClient(clients: AgencyClient[], ref: string): AgencyClient;
|
|
22
|
+
/** Look a client up by id or exact name, archived ones included. */
|
|
23
|
+
export declare function resolveClient(ctx: Context, ref: string): Promise<AgencyClient>;
|
|
24
|
+
/** Pick one environment by id or exact name. */
|
|
25
|
+
export declare function matchEnvironment(machines: Machine[], ref: string): Machine;
|
|
26
|
+
/**
|
|
27
|
+
* The window for `qoren account costs`, as unix ms.
|
|
28
|
+
*
|
|
29
|
+
* Accepts any ISO date or date-time. A bare date for --to means the whole of
|
|
30
|
+
* that day (UTC), because "--to 2026-09-30" read as midnight would silently
|
|
31
|
+
* leave the 30th out. With nothing given, the last 30 days.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseCostWindow(from: string | undefined, to: string | undefined, now?: number): {
|
|
34
|
+
from: number;
|
|
35
|
+
to: number;
|
|
36
|
+
};
|
|
37
|
+
export type CostRow = {
|
|
38
|
+
label: string;
|
|
39
|
+
credits: number;
|
|
40
|
+
total?: boolean;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The rows `qoren account costs` prints: each client by spend, then the
|
|
44
|
+
* environments with no client, then account-level spend, then spend from
|
|
45
|
+
* before cost tracking (only when there is some), then the total.
|
|
46
|
+
*/
|
|
47
|
+
export declare function costRows(costs: ClientCosts): CostRow[];
|
|
48
|
+
/**
|
|
49
|
+
* The whole window by category: every client, no client, the account line
|
|
50
|
+
* and spend from before tracking. Categories with no spend are left out.
|
|
51
|
+
*/
|
|
52
|
+
export declare function categoryRows(costs: ClientCosts): CostRow[];
|
|
53
|
+
/** Credits to two decimal places at most, without trailing zeros. */
|
|
54
|
+
export declare const formatCredits: (credits: number) => string;
|
|
55
|
+
/** Dollars are credits / 1000. */
|
|
56
|
+
export declare const formatDollars: (credits: number) => string;
|
|
57
|
+
/** Print a costs response as tables plus the caveats a reader needs. */
|
|
58
|
+
export declare function renderCosts(costs: ClientCosts): void;
|
|
59
|
+
export declare function clientsCommands(program: Command, global: () => GlobalOptions): void;
|
|
60
|
+
/** What `qoren clients hologram` prints. The URL alone goes to stdout, so it can be piped. */
|
|
61
|
+
export declare function hologramDetails(client: AgencyClient, link: ClientHologramLink, revoked: boolean): void;
|
|
62
|
+
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../src/commands/clients.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EAEvB,KAAK,OAAO,EACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAuB,KAAK,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAStF,2DAA2D;AAC3D,eAAO,MAAM,gBAAgB,8CAA8C,CAAC;AAE5E;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAYtD;AAED,iEAAiE;AACjE,wBAAsB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAM3D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,YAAY,EAAE,EACvB,GAAG,EAAE,MAAM,GACV,YAAY,CAed;AAED,oEAAoE;AACpE,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,CAAC,CAKvB;AAED,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAa1E;AAKD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,GAAG,GAAE,MAAmB,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAiB9B;AAED,MAAM,MAAM,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1E;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,EAAE,CAiBtD;AAWD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,EAAE,CAU1D;AAED,qEAAqE;AACrE,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MACP,CAAC;AAE1C,kCAAkC;AAClC,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MACb,CAAC;AAIpC,wEAAwE;AACxE,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAgCpD;AAwDD,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,QAqG5E;AAED,8FAA8F;AAC9F,wBAAgB,eAAe,CAC7B,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,OAAO,GACf,IAAI,CAmBN"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import { QorenError, } from "@qoren/sdk";
|
|
2
|
+
import { requireContext, run } from "../context.js";
|
|
3
|
+
import { age, bold, details, dim, emit, note, table } from "../output.js";
|
|
4
|
+
// Agency clients: the businesses an agency runs environments and agents for.
|
|
5
|
+
//
|
|
6
|
+
// The API calls them customers; this CLI never says so. Everything here is
|
|
7
|
+
// gated per account upstream, and an account without the feature is told so
|
|
8
|
+
// in one sentence rather than being sent to sign in again.
|
|
9
|
+
/** The upstream refusal for an account without clients. */
|
|
10
|
+
export const CLIENTS_DISABLED = "Clients are not enabled for this account.";
|
|
11
|
+
/**
|
|
12
|
+
* The feature refusal as a plain failure; any other error untouched.
|
|
13
|
+
*
|
|
14
|
+
* A bare 403 exits 3 ("sign in again"), which is the wrong advice here: the
|
|
15
|
+
* credential is fine, the account just does not have the feature. The message
|
|
16
|
+
* is the server's own, so it stays one clean sentence.
|
|
17
|
+
*/
|
|
18
|
+
export function clientsGateError(err) {
|
|
19
|
+
if (err instanceof QorenError &&
|
|
20
|
+
err.status === 403 &&
|
|
21
|
+
// The Custom agent routes say so with a code; the older client routes
|
|
22
|
+
// only in words.
|
|
23
|
+
(err.code === "agency_clients_disabled" ||
|
|
24
|
+
/clients are not enabled/i.test(err.message))) {
|
|
25
|
+
return new Error(err.message || CLIENTS_DISABLED);
|
|
26
|
+
}
|
|
27
|
+
return err;
|
|
28
|
+
}
|
|
29
|
+
/** Await a gated call, reporting the feature refusal cleanly. */
|
|
30
|
+
export async function gated(call) {
|
|
31
|
+
try {
|
|
32
|
+
return await call;
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
throw clientsGateError(err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Pick one client by id or exact name. Ids win, then active names (unique
|
|
40
|
+
* upstream), then an archived name when only one matches. Pure so the rules
|
|
41
|
+
* are testable without a control plane.
|
|
42
|
+
*/
|
|
43
|
+
export function matchClient(clients, ref) {
|
|
44
|
+
const byId = clients.find((c) => c.id === ref);
|
|
45
|
+
if (byId)
|
|
46
|
+
return byId;
|
|
47
|
+
const named = clients.filter((c) => c.name === ref);
|
|
48
|
+
const active = named.filter((c) => c.archivedAt === null);
|
|
49
|
+
if (active.length === 1 && active[0])
|
|
50
|
+
return active[0];
|
|
51
|
+
if (active.length === 0 && named.length === 1 && named[0])
|
|
52
|
+
return named[0];
|
|
53
|
+
if (named.length > 1) {
|
|
54
|
+
throw new Error(`More than one client is named "${ref}". Use its id (see qoren clients list --archived).`);
|
|
55
|
+
}
|
|
56
|
+
throw new Error(`No client has the id or name "${ref}". Run qoren clients list to see them.`);
|
|
57
|
+
}
|
|
58
|
+
/** Look a client up by id or exact name, archived ones included. */
|
|
59
|
+
export async function resolveClient(ctx, ref) {
|
|
60
|
+
const clients = await gated(ctx.qoren.clients.list({ includeArchived: true }));
|
|
61
|
+
return matchClient(clients, ref);
|
|
62
|
+
}
|
|
63
|
+
/** Pick one environment by id or exact name. */
|
|
64
|
+
export function matchEnvironment(machines, ref) {
|
|
65
|
+
const byId = machines.find((m) => m.id === ref);
|
|
66
|
+
if (byId)
|
|
67
|
+
return byId;
|
|
68
|
+
const named = machines.filter((m) => m.name === ref);
|
|
69
|
+
if (named.length === 1 && named[0])
|
|
70
|
+
return named[0];
|
|
71
|
+
if (named.length > 1) {
|
|
72
|
+
throw new Error(`More than one environment is named "${ref}". Use its id (see qoren env ls).`);
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`No environment has the id or name "${ref}". Run qoren env ls to see them.`);
|
|
75
|
+
}
|
|
76
|
+
const DAY_MS = 86_400_000;
|
|
77
|
+
const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
78
|
+
/**
|
|
79
|
+
* The window for `qoren account costs`, as unix ms.
|
|
80
|
+
*
|
|
81
|
+
* Accepts any ISO date or date-time. A bare date for --to means the whole of
|
|
82
|
+
* that day (UTC), because "--to 2026-09-30" read as midnight would silently
|
|
83
|
+
* leave the 30th out. With nothing given, the last 30 days.
|
|
84
|
+
*/
|
|
85
|
+
export function parseCostWindow(from, to, now = Date.now()) {
|
|
86
|
+
const parse = (value, flag) => {
|
|
87
|
+
const ms = Date.parse(value);
|
|
88
|
+
if (Number.isNaN(ms)) {
|
|
89
|
+
throw new Error(`${flag} must be an ISO date such as 2026-09-01, not "${value}".`);
|
|
90
|
+
}
|
|
91
|
+
return ms;
|
|
92
|
+
};
|
|
93
|
+
const end = to === undefined
|
|
94
|
+
? now
|
|
95
|
+
: parse(to, "--to") + (DATE_ONLY.test(to.trim()) ? DAY_MS : 0);
|
|
96
|
+
const start = from === undefined ? end - 30 * DAY_MS : parse(from, "--from");
|
|
97
|
+
if (start >= end)
|
|
98
|
+
throw new Error("--from must be before --to.");
|
|
99
|
+
return { from: start, to: end };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The rows `qoren account costs` prints: each client by spend, then the
|
|
103
|
+
* environments with no client, then account-level spend, then spend from
|
|
104
|
+
* before cost tracking (only when there is some), then the total.
|
|
105
|
+
*/
|
|
106
|
+
export function costRows(costs) {
|
|
107
|
+
const named = costs.customers
|
|
108
|
+
.filter((c) => c.customerId !== null)
|
|
109
|
+
.map((c) => ({ label: c.name ?? c.customerId ?? "", credits: c.credits }))
|
|
110
|
+
.sort((a, b) => b.credits - a.credits);
|
|
111
|
+
const unassigned = costs.customers
|
|
112
|
+
.filter((c) => c.customerId === null)
|
|
113
|
+
.reduce((sum, c) => sum + c.credits, 0);
|
|
114
|
+
return [
|
|
115
|
+
...named,
|
|
116
|
+
{ label: "No client", credits: unassigned },
|
|
117
|
+
{ label: "Account", credits: costs.account.credits },
|
|
118
|
+
...(costs.beforeTracking.credits > 0
|
|
119
|
+
? [{ label: "Before client tracking", credits: costs.beforeTracking.credits }]
|
|
120
|
+
: []),
|
|
121
|
+
{ label: "Total", credits: costs.totalCredits, total: true },
|
|
122
|
+
];
|
|
123
|
+
}
|
|
124
|
+
/** The categories, in the order the console lists them. */
|
|
125
|
+
const CATEGORIES = [
|
|
126
|
+
{ key: "environment", label: "Hosting" },
|
|
127
|
+
{ key: "llm", label: "Models" },
|
|
128
|
+
{ key: "webSearch", label: "Web search" },
|
|
129
|
+
{ key: "runs", label: "Custom agent runs" },
|
|
130
|
+
{ key: "tools", label: "Custom agent tools" },
|
|
131
|
+
];
|
|
132
|
+
/**
|
|
133
|
+
* The whole window by category: every client, no client, the account line
|
|
134
|
+
* and spend from before tracking. Categories with no spend are left out.
|
|
135
|
+
*/
|
|
136
|
+
export function categoryRows(costs) {
|
|
137
|
+
const all = [
|
|
138
|
+
...costs.customers.map((c) => c.byKind),
|
|
139
|
+
costs.account.byKind,
|
|
140
|
+
costs.beforeTracking.byKind,
|
|
141
|
+
];
|
|
142
|
+
return CATEGORIES.map(({ key, label }) => ({
|
|
143
|
+
label,
|
|
144
|
+
credits: all.reduce((sum, b) => sum + b[key], 0),
|
|
145
|
+
})).filter((r) => r.credits > 0);
|
|
146
|
+
}
|
|
147
|
+
/** Credits to two decimal places at most, without trailing zeros. */
|
|
148
|
+
export const formatCredits = (credits) => String(Math.round(credits * 100) / 100);
|
|
149
|
+
/** Dollars are credits / 1000. */
|
|
150
|
+
export const formatDollars = (credits) => `$${(credits / 1000).toFixed(2)}`;
|
|
151
|
+
const day = (ms) => new Date(ms).toISOString().slice(0, 10);
|
|
152
|
+
/** Print a costs response as tables plus the caveats a reader needs. */
|
|
153
|
+
export function renderCosts(costs) {
|
|
154
|
+
note(dim(`${day(costs.from)} to ${day(costs.to)}`));
|
|
155
|
+
costTable(costRows(costs), "client");
|
|
156
|
+
const categories = categoryRows(costs);
|
|
157
|
+
if (categories.length > 0) {
|
|
158
|
+
process.stdout.write("\n");
|
|
159
|
+
costTable(categories, "category");
|
|
160
|
+
}
|
|
161
|
+
if (costs.trackingSince === null) {
|
|
162
|
+
note(dim("No spend has been attributed to clients yet."));
|
|
163
|
+
}
|
|
164
|
+
else if (costs.trackingSince > costs.from) {
|
|
165
|
+
note(dim(`Spend is broken down by client from ${day(costs.trackingSince)}; earlier spend is under "Before client tracking".`));
|
|
166
|
+
}
|
|
167
|
+
if (costs.beforeTracking.estimated) {
|
|
168
|
+
note(dim("Model spend from before client tracking is estimated from the raw model cost."));
|
|
169
|
+
}
|
|
170
|
+
if (costs.pendingSettlements > 0) {
|
|
171
|
+
note(dim(`${String(costs.pendingSettlements)} ${costs.pendingSettlements === 1 ? "charge is" : "charges are"} still settling and not included above.`));
|
|
172
|
+
}
|
|
173
|
+
note(dim("Mailbox charges and the plan fee are not included; see Clients in the console."));
|
|
174
|
+
}
|
|
175
|
+
function costTable(rows, header) {
|
|
176
|
+
table(rows, [
|
|
177
|
+
{
|
|
178
|
+
header,
|
|
179
|
+
value: (r) => (r.total ? bold(r.label) : r.label),
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
header: "credits",
|
|
183
|
+
value: (r) => {
|
|
184
|
+
const text = formatCredits(r.credits);
|
|
185
|
+
return r.total ? bold(text) : text;
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
header: "dollars",
|
|
190
|
+
value: (r) => {
|
|
191
|
+
const text = formatDollars(r.credits);
|
|
192
|
+
return r.total ? bold(text) : text;
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
]);
|
|
196
|
+
}
|
|
197
|
+
function clientTable(rows, showStatus) {
|
|
198
|
+
table(rows, [
|
|
199
|
+
{ header: "id", value: (c) => c.id },
|
|
200
|
+
{ header: "name", value: (c) => c.name },
|
|
201
|
+
{ header: "email", value: (c) => c.contactEmail ?? "" },
|
|
202
|
+
{ header: "environments", value: (c) => String(c.environmentCount) },
|
|
203
|
+
{ header: "agents", value: (c) => String(c.agentCount) },
|
|
204
|
+
...(showStatus
|
|
205
|
+
? [
|
|
206
|
+
{
|
|
207
|
+
header: "status",
|
|
208
|
+
value: (c) => (c.archivedAt ? "archived" : "active"),
|
|
209
|
+
},
|
|
210
|
+
]
|
|
211
|
+
: []),
|
|
212
|
+
{ header: "age", value: (c) => age(c.createdAt) },
|
|
213
|
+
]);
|
|
214
|
+
}
|
|
215
|
+
function clientDetails(c) {
|
|
216
|
+
details([
|
|
217
|
+
["Id", c.id],
|
|
218
|
+
["Name", c.name],
|
|
219
|
+
["Email", c.contactEmail ?? ""],
|
|
220
|
+
["Notes", c.notes ?? ""],
|
|
221
|
+
["Environments", String(c.environmentCount)],
|
|
222
|
+
["Agents", String(c.agentCount)],
|
|
223
|
+
["Status", c.archivedAt ? `archived ${c.archivedAt}` : "active"],
|
|
224
|
+
]);
|
|
225
|
+
}
|
|
226
|
+
export function clientsCommands(program, global) {
|
|
227
|
+
const clients = program
|
|
228
|
+
.command("clients")
|
|
229
|
+
.alias("client")
|
|
230
|
+
.description("Manage the clients your environments are run for");
|
|
231
|
+
clients
|
|
232
|
+
.command("list")
|
|
233
|
+
.alias("ls")
|
|
234
|
+
.description("List your clients")
|
|
235
|
+
.option("--archived", "include archived clients")
|
|
236
|
+
.action((options) => run(async () => {
|
|
237
|
+
const ctx = requireContext(global());
|
|
238
|
+
const rows = await gated(ctx.qoren.clients.list({ includeArchived: options.archived === true }));
|
|
239
|
+
emit(rows, () => clientTable(rows, options.archived === true));
|
|
240
|
+
})());
|
|
241
|
+
clients
|
|
242
|
+
.command("create <name>")
|
|
243
|
+
.description("Add a client")
|
|
244
|
+
.option("--email <email>", "contact email")
|
|
245
|
+
.option("--notes <notes>", "free-form notes")
|
|
246
|
+
.action((name, options) => run(async () => {
|
|
247
|
+
const ctx = requireContext(global());
|
|
248
|
+
const created = await gated(ctx.qoren.clients.create({
|
|
249
|
+
name,
|
|
250
|
+
...(options.email !== undefined
|
|
251
|
+
? { contactEmail: options.email }
|
|
252
|
+
: {}),
|
|
253
|
+
...(options.notes !== undefined ? { notes: options.notes } : {}),
|
|
254
|
+
}));
|
|
255
|
+
emit(created, () => {
|
|
256
|
+
clientDetails(created);
|
|
257
|
+
note(`Client ${bold(created.name)} added. Assign an environment with qoren env assign <environment> ${created.id}.`);
|
|
258
|
+
});
|
|
259
|
+
})());
|
|
260
|
+
clients
|
|
261
|
+
.command("rename <client> <name>")
|
|
262
|
+
.description("Rename a client (by id or current name)")
|
|
263
|
+
.action((ref, name) => run(async () => {
|
|
264
|
+
const ctx = requireContext(global());
|
|
265
|
+
const client = await resolveClient(ctx, ref);
|
|
266
|
+
const updated = await gated(ctx.qoren.clients.update(client.id, { name }));
|
|
267
|
+
emit(updated, () => note(`Renamed to ${bold(updated.name)}.`));
|
|
268
|
+
})());
|
|
269
|
+
clients
|
|
270
|
+
.command("archive <client>")
|
|
271
|
+
.description("Archive a client (by id or name); its environments must be unassigned first")
|
|
272
|
+
.action((ref) => run(async () => {
|
|
273
|
+
const ctx = requireContext(global());
|
|
274
|
+
const client = await resolveClient(ctx, ref);
|
|
275
|
+
const archived = await gated(ctx.qoren.clients.archive(client.id));
|
|
276
|
+
emit(archived, () => note(`Client ${bold(archived.name)} archived. Its cost history is kept.`));
|
|
277
|
+
})());
|
|
278
|
+
clients
|
|
279
|
+
.command("hologram <client>")
|
|
280
|
+
.description("Show, create or revoke a client's public hologram link (account owners only)")
|
|
281
|
+
.option("--new", "create the link, or replace it (the old URL stops working)")
|
|
282
|
+
.option("--revoke", "switch the link off")
|
|
283
|
+
.action((ref, options) => run(async () => {
|
|
284
|
+
if (options.new && options.revoke) {
|
|
285
|
+
throw new Error("Use --new or --revoke, not both.");
|
|
286
|
+
}
|
|
287
|
+
const ctx = requireContext(global());
|
|
288
|
+
const client = await resolveClient(ctx, ref);
|
|
289
|
+
const link = await gated(options.revoke
|
|
290
|
+
? ctx.qoren.clients.revokeHologramLink(client.id)
|
|
291
|
+
: options.new
|
|
292
|
+
? ctx.qoren.clients.createHologramLink(client.id)
|
|
293
|
+
: ctx.qoren.clients.hologramLink(client.id));
|
|
294
|
+
emit(link, () => hologramDetails(client, link, options.revoke === true));
|
|
295
|
+
})());
|
|
296
|
+
}
|
|
297
|
+
/** What `qoren clients hologram` prints. The URL alone goes to stdout, so it can be piped. */
|
|
298
|
+
export function hologramDetails(client, link, revoked) {
|
|
299
|
+
if (!link.active) {
|
|
300
|
+
note(revoked
|
|
301
|
+
? `The hologram link for ${bold(client.name)} is off. Its URL no longer works.`
|
|
302
|
+
: `${bold(client.name)} has no hologram link. Create one with qoren clients hologram ${client.id} --new.`);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (link.url)
|
|
306
|
+
process.stdout.write(`${link.url}\n`);
|
|
307
|
+
else
|
|
308
|
+
note(`The link for ${bold(client.name)} is on, but its URL cannot be shown again. Replace it with --new to get a new URL.`);
|
|
309
|
+
note(dim(`Anyone with this URL sees ${client.name}'s environments and agents, live, without signing in. Created ${link.createdAt ?? ""}.`));
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../../src/commands/clients.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/commands/console.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAUxE,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,QAoB3E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { requireContext, run } from "../context.js";
|
|
2
|
+
import { isJsonMode } from "../output.js";
|
|
3
|
+
// The interactive console.
|
|
4
|
+
//
|
|
5
|
+
// Ink and React are a good deal heavier than the rest of this package, and most
|
|
6
|
+
// invocations are a single command in a script that will never draw a frame. So
|
|
7
|
+
// the console is imported dynamically: `qoren env ls --json` pays nothing for
|
|
8
|
+
// it, and only someone who actually asked for a console waits for it to load.
|
|
9
|
+
export function consoleCommand(program, global) {
|
|
10
|
+
program
|
|
11
|
+
.command("tui")
|
|
12
|
+
.alias("console")
|
|
13
|
+
.description("Open the interactive console")
|
|
14
|
+
.action(() => run(async () => {
|
|
15
|
+
if (isJsonMode()) {
|
|
16
|
+
// --json promises stdout carries data and nothing else. A console
|
|
17
|
+
// that took over the screen would break that promise rather than
|
|
18
|
+
// bend it, so say so instead of half-honouring both.
|
|
19
|
+
throw new Error("The console cannot run with --json. Drop the flag, or use the commands.");
|
|
20
|
+
}
|
|
21
|
+
const ctx = requireContext(global());
|
|
22
|
+
const { runConsole } = await import("../tui/index.js");
|
|
23
|
+
await runConsole(ctx);
|
|
24
|
+
})());
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/commands/console.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,GAAG,EAAsB,MAAM,eAAe,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,2BAA2B;AAC3B,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,8EAA8E;AAC9E,8EAA8E;AAE9E,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,MAA2B;IAC1E,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,KAAK,CAAC,SAAS,CAAC;SAChB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,GAAG,EAAE,CACX,GAAG,CAAC,KAAK,IAAI,EAAE;QACb,IAAI,UAAU,EAAE,EAAE,CAAC;YACjB,kEAAkE;YAClE,iEAAiE;YACjE,qDAAqD;YACrD,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC;QACrC,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACvD,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC,CAAC,EAAE,CACL,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type AddChannelInput, type DesignRun } from "@qoren/sdk";
|
|
3
|
+
import { type GlobalOptions } from "../context.js";
|
|
4
|
+
export declare function isTerminalRun(status: string): boolean;
|
|
5
|
+
/** How long a run took, or has been going. */
|
|
6
|
+
export declare function runDuration(r: Pick<DesignRun, "startedAt" | "endedAt">, now?: number): string;
|
|
7
|
+
/** A run's status with what it waits on, e.g. "waiting (approval)". */
|
|
8
|
+
export declare function runStatus(r: Pick<DesignRun, "status" | "waitingOn">): string;
|
|
9
|
+
export declare function printRun(r: DesignRun): void;
|
|
10
|
+
/**
|
|
11
|
+
* Poll a run until it finishes or the time is up. Says once what a waiting run
|
|
12
|
+
* waits on, because an approval can take hours and silence looks like a hang.
|
|
13
|
+
* `read` fetches the run: an agent's run or a design's test run.
|
|
14
|
+
*/
|
|
15
|
+
export declare function waitForRun(read: () => Promise<DesignRun>, timeoutSeconds: number): Promise<{
|
|
16
|
+
run: DesignRun;
|
|
17
|
+
finished: boolean;
|
|
18
|
+
}>;
|
|
19
|
+
/** Read `--timeout` for a `--wait`. */
|
|
20
|
+
export declare function parseWaitTimeout(value: string): number;
|
|
21
|
+
/** The end of a waited-for run, for a person: outcome, cost, result. Sets the
|
|
22
|
+
* exit code when it did not succeed or is still going. */
|
|
23
|
+
export declare function reportWaitedRun({ run: r, finished }: {
|
|
24
|
+
run: DesignRun;
|
|
25
|
+
finished: boolean;
|
|
26
|
+
}, timeoutText: string, checkBack: string, options?: {
|
|
27
|
+
trace?: boolean;
|
|
28
|
+
}): void;
|
|
29
|
+
export type ChannelAddOptions = {
|
|
30
|
+
botToken?: string;
|
|
31
|
+
signingSecret?: string;
|
|
32
|
+
guild?: string;
|
|
33
|
+
botName?: string;
|
|
34
|
+
allMessages?: boolean;
|
|
35
|
+
};
|
|
36
|
+
/** The connect request for `channel add`, refusing what the control plane
|
|
37
|
+
* would refuse before anything is sent: an unknown kind, no bot token, a Slack
|
|
38
|
+
* app without its signing secret, or a Discord bot without its server id
|
|
39
|
+
* (the bot only ignores other servers when it is bound to one). */
|
|
40
|
+
export declare function channelInput(kind: string, options: ChannelAddOptions): AddChannelInput;
|
|
41
|
+
export declare function customAgentCommands(agent: Command, global: () => GlobalOptions): void;
|
|
42
|
+
//# sourceMappingURL=customAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customAgent.d.ts","sourceRoot":"","sources":["../../src/commands/customAgent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAEL,KAAK,eAAe,EAGpB,KAAK,SAAS,EAEf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AA8BxE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,8CAA8C;AAC9C,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC,EAAE,GAAG,SAAa,GAAG,MAAM,CAMjG;AAED,uEAAuE;AACvE,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,QAAQ,GAAG,WAAW,CAAC,GAAG,MAAM,CAI5E;AA0BD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,CA2B3C;AAID;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,EAC9B,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,CAchD;AAED,uCAAuC;AACvC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMtD;AAED;0DAC0D;AAC1D,wBAAgB,eAAe,CAC7B,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,EAC3D,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAChC,IAAI,CAeN;AAWD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF;;;mEAGmE;AACnE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,eAAe,CAkCtF;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,QA6U9E"}
|