@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,40 @@
|
|
|
1
|
+
// Task chaining, as typed on the command line.
|
|
2
|
+
//
|
|
3
|
+
// A scheduled task can read the latest output of other tasks of the same
|
|
4
|
+
// agent (or its own previous run) before its prompt on every run. On the
|
|
5
|
+
// command line that is a repeatable `--context-from <task>`, taking a task id,
|
|
6
|
+
// a task name, or "self"; the control plane resolves names and "self" to ids.
|
|
7
|
+
// `--no-context-from` on task-set clears the list.
|
|
8
|
+
/** The control plane refuses more than this many. */
|
|
9
|
+
export const MAX_CONTEXT_FROM = 5;
|
|
10
|
+
export const CONTEXT_FROM_HELP = "read the latest output of another task of this agent before each run: " +
|
|
11
|
+
"a task id, a task name, or \"self\" for this task's own previous run. " +
|
|
12
|
+
`Repeat for more, up to ${MAX_CONTEXT_FROM}`;
|
|
13
|
+
/** Commander collector for the repeatable `--context-from`. */
|
|
14
|
+
export function collectContextFrom(value, previous) {
|
|
15
|
+
return [...(previous ?? []), value];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The `contextFrom` field for a task write. `undefined` (no flag) leaves it
|
|
19
|
+
* out, so a create reads nothing and a replace keeps what it had; `false`
|
|
20
|
+
* (`--no-context-from`) clears it.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveContextFrom(option) {
|
|
23
|
+
if (option === undefined)
|
|
24
|
+
return undefined;
|
|
25
|
+
if (option === false)
|
|
26
|
+
return [];
|
|
27
|
+
const refs = option.map((ref) => ref.trim()).filter(Boolean);
|
|
28
|
+
if (refs.length === 0)
|
|
29
|
+
throw new Error("--context-from needs a task id, a task name, or \"self\".");
|
|
30
|
+
if (refs.length > MAX_CONTEXT_FROM)
|
|
31
|
+
throw new Error(`A task can read the output of at most ${MAX_CONTEXT_FROM} tasks.`);
|
|
32
|
+
return refs;
|
|
33
|
+
}
|
|
34
|
+
/** How the task table shows a chain: the names it reads, "self" for its own previous run. */
|
|
35
|
+
export function describeChain(task, tasks) {
|
|
36
|
+
return (task.contextFrom ?? [])
|
|
37
|
+
.map((id) => (id === task.id ? "self" : (tasks.find((t) => t.id === id)?.name ?? id)))
|
|
38
|
+
.join(", ");
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=taskChain.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskChain.js","sourceRoot":"","sources":["../src/taskChain.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,yEAAyE;AACzE,yEAAyE;AACzE,+EAA+E;AAC/E,8EAA8E;AAC9E,mDAAmD;AAEnD,qDAAqD;AACrD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,iBAAiB,GAC5B,wEAAwE;IACxE,wEAAwE;IACxE,0BAA0B,gBAAgB,EAAE,CAAC;AAE/C,+DAA+D;AAC/D,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,QAA8B;IAC9E,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAoC;IACrE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IACpG,IAAI,IAAI,CAAC,MAAM,GAAG,gBAAgB;QAChC,MAAM,IAAI,KAAK,CAAC,yCAAyC,gBAAgB,SAAS,CAAC,CAAC;IACtF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,aAAa,CAC3B,IAAmD,EACnD,KAA8C;IAE9C,OAAO,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;SAC5B,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;SACrF,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ScheduledTaskDeliveryPolicy } from "@qoren/sdk";
|
|
2
|
+
export declare const DELIVERY_POLICIES: readonly ScheduledTaskDeliveryPolicy[];
|
|
3
|
+
/**
|
|
4
|
+
* A chat target: `platform`, `platform:chatId` or `platform:chatId:threadId`.
|
|
5
|
+
* Kept in step with the control plane's check (and @qoren/sdk's
|
|
6
|
+
* CHAT_TARGET_PATTERN); copied rather than imported so this CLI still runs
|
|
7
|
+
* against an older published SDK.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CHAT_TARGET_RE: RegExp;
|
|
10
|
+
export declare const DELIVERY_HELP = "activity-only, all-channels (every chat channel, Hermes only), or chat (needs --deliver-to)";
|
|
11
|
+
export declare const DELIVER_TO_HELP: string;
|
|
12
|
+
export type DeliveryFields = {
|
|
13
|
+
deliveryPolicy?: ScheduledTaskDeliveryPolicy;
|
|
14
|
+
deliveryTarget?: string | null;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The delivery fields for a task write, from `--delivery` / `--deliver-to`.
|
|
18
|
+
* With neither flag, a create leaves delivery to the server's default and a
|
|
19
|
+
* replace (given the task as it stands) keeps what it had, target included.
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveDelivery(options: {
|
|
22
|
+
delivery?: string;
|
|
23
|
+
deliverTo?: string;
|
|
24
|
+
}, existing?: {
|
|
25
|
+
deliveryPolicy: ScheduledTaskDeliveryPolicy;
|
|
26
|
+
deliveryTarget?: string | null;
|
|
27
|
+
}): DeliveryFields;
|
|
28
|
+
/** How the task table shows delivery: the policy, or the chat it posts to. */
|
|
29
|
+
export declare function describeDelivery(task: {
|
|
30
|
+
deliveryPolicy: string;
|
|
31
|
+
deliveryTarget?: string | null;
|
|
32
|
+
}): string;
|
|
33
|
+
//# sourceMappingURL=taskDelivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskDelivery.d.ts","sourceRoot":"","sources":["../src/taskDelivery.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D,eAAO,MAAM,iBAAiB,EAAE,SAAS,2BAA2B,EAInE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QACmD,CAAC;AAE/E,eAAO,MAAM,aAAa,gGACqE,CAAC;AAEhG,eAAO,MAAM,eAAe,QAKmC,CAAC;AAEhE,MAAM,MAAM,cAAc,GAAG;IAC3B,cAAc,CAAC,EAAE,2BAA2B,CAAC;IAC7C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AASF;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAClD,QAAQ,CAAC,EAAE;IACT,cAAc,EAAE,2BAA2B,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GACA,cAAc,CA2BhB;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,GAAG,MAAM,CAIT"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Where a scheduled task's results go, as typed on the command line.
|
|
2
|
+
//
|
|
3
|
+
// `--delivery` picks the policy by name; `--deliver-to` names one chat and
|
|
4
|
+
// implies the "chat" policy, which is how an owner points a task at a Telegram
|
|
5
|
+
// group or a Slack channel. The target is checked here with the same pattern
|
|
6
|
+
// the control plane uses, so a typo fails before a request is made, with the
|
|
7
|
+
// accepted forms spelled out, instead of as a bare 400.
|
|
8
|
+
export const DELIVERY_POLICIES = [
|
|
9
|
+
"activity-only",
|
|
10
|
+
"all-channels",
|
|
11
|
+
"chat",
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* A chat target: `platform`, `platform:chatId` or `platform:chatId:threadId`.
|
|
15
|
+
* Kept in step with the control plane's check (and @qoren/sdk's
|
|
16
|
+
* CHAT_TARGET_PATTERN); copied rather than imported so this CLI still runs
|
|
17
|
+
* against an older published SDK.
|
|
18
|
+
*/
|
|
19
|
+
export const CHAT_TARGET_RE = /^[a-z][a-z0-9_-]{0,31}(:[A-Za-z0-9_@.+-]{1,128}(:[A-Za-z0-9_.-]{1,64})?)?$/;
|
|
20
|
+
export const DELIVERY_HELP = "activity-only, all-channels (every chat channel, Hermes only), or chat (needs --deliver-to)";
|
|
21
|
+
export const DELIVER_TO_HELP = "send each run's result to one chat (sets --delivery chat): " +
|
|
22
|
+
"PLATFORM for that platform's home channel (Hermes only), " +
|
|
23
|
+
"PLATFORM:CHAT_ID for one chat, or PLATFORM:CHAT_ID:THREAD_ID for a thread or topic in it, " +
|
|
24
|
+
"e.g. telegram:-1001234567890, telegram:-1001234567890:42, slack:C0123ABC. " +
|
|
25
|
+
"PLATFORM must be one of the agent's connected chat channels";
|
|
26
|
+
function badTarget(target) {
|
|
27
|
+
return new Error(`"${target}" is not a chat target. Use PLATFORM, PLATFORM:CHAT_ID or PLATFORM:CHAT_ID:THREAD_ID, ` +
|
|
28
|
+
"for example telegram:-1001234567890 or slack:C0123ABC (lowercase platform name, no spaces).");
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The delivery fields for a task write, from `--delivery` / `--deliver-to`.
|
|
32
|
+
* With neither flag, a create leaves delivery to the server's default and a
|
|
33
|
+
* replace (given the task as it stands) keeps what it had, target included.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveDelivery(options, existing) {
|
|
36
|
+
const { delivery, deliverTo } = options;
|
|
37
|
+
if (delivery !== undefined && !DELIVERY_POLICIES.includes(delivery))
|
|
38
|
+
throw new Error(`--delivery must be one of ${DELIVERY_POLICIES.join(", ")}.`);
|
|
39
|
+
if (deliverTo !== undefined) {
|
|
40
|
+
const target = deliverTo.trim();
|
|
41
|
+
if (!CHAT_TARGET_RE.test(target))
|
|
42
|
+
throw badTarget(deliverTo);
|
|
43
|
+
if (delivery !== undefined && delivery !== "chat")
|
|
44
|
+
throw new Error(`--deliver-to sends to one chat, so it cannot be combined with --delivery ${delivery}.`);
|
|
45
|
+
return { deliveryPolicy: "chat", deliveryTarget: target };
|
|
46
|
+
}
|
|
47
|
+
if (delivery === "chat") {
|
|
48
|
+
if (existing?.deliveryPolicy === "chat" && existing.deliveryTarget)
|
|
49
|
+
return { deliveryPolicy: "chat", deliveryTarget: existing.deliveryTarget };
|
|
50
|
+
throw new Error("--delivery chat needs --deliver-to <target>, for example --deliver-to telegram:-1001234567890.");
|
|
51
|
+
}
|
|
52
|
+
if (delivery !== undefined)
|
|
53
|
+
return { deliveryPolicy: delivery, deliveryTarget: null };
|
|
54
|
+
if (existing)
|
|
55
|
+
return {
|
|
56
|
+
deliveryPolicy: existing.deliveryPolicy,
|
|
57
|
+
deliveryTarget: existing.deliveryPolicy === "chat" ? (existing.deliveryTarget ?? null) : null,
|
|
58
|
+
};
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
/** How the task table shows delivery: the policy, or the chat it posts to. */
|
|
62
|
+
export function describeDelivery(task) {
|
|
63
|
+
if (task.deliveryPolicy === "chat")
|
|
64
|
+
return task.deliveryTarget ? `chat ${task.deliveryTarget}` : "chat";
|
|
65
|
+
return task.deliveryPolicy;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=taskDelivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"taskDelivery.js","sourceRoot":"","sources":["../src/taskDelivery.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,2EAA2E;AAC3E,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,wDAAwD;AAIxD,MAAM,CAAC,MAAM,iBAAiB,GAA2C;IACvE,eAAe;IACf,cAAc;IACd,MAAM;CACP,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GACzB,4EAA4E,CAAC;AAE/E,MAAM,CAAC,MAAM,aAAa,GACxB,6FAA6F,CAAC;AAEhG,MAAM,CAAC,MAAM,eAAe,GAC1B,6DAA6D;IAC7D,2DAA2D;IAC3D,4FAA4F;IAC5F,4EAA4E;IAC5E,6DAA6D,CAAC;AAOhE,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,IAAI,KAAK,CACd,IAAI,MAAM,wFAAwF;QAChG,6FAA6F,CAChG,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAC7B,OAAkD,EAClD,QAGC;IAED,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IACxC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAuC,CAAC;QAChG,MAAM,IAAI,KAAK,CAAC,6BAA6B,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEhF,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,MAAM,SAAS,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,MAAM;YAC/C,MAAM,IAAI,KAAK,CAAC,4EAA4E,QAAQ,GAAG,CAAC,CAAC;QAC3G,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC;IAC5D,CAAC;IAED,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,IAAI,QAAQ,EAAE,cAAc,KAAK,MAAM,IAAI,QAAQ,CAAC,cAAc;YAChE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAC;IACpH,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS;QACxB,OAAO,EAAE,cAAc,EAAE,QAAuC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IAE3F,IAAI,QAAQ;QACV,OAAO;YACL,cAAc,EAAE,QAAQ,CAAC,cAAc;YACvC,cAAc,EAAE,QAAQ,CAAC,cAAc,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;SAC9F,CAAC;IACJ,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,IAGhC;IACC,IAAI,IAAI,CAAC,cAAc,KAAK,MAAM;QAChC,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACtE,OAAO,IAAI,CAAC,cAAc,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AA0N7C,wBAAgB,GAAG,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,+BAQpD"}
|
package/dist/tui/app.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Box, Text, useApp, useInput, useWindowSize } from "ink";
|
|
4
|
+
import { UiProvider, useUi } from "./overlay.js";
|
|
5
|
+
import { SessionProvider, useSession } from "./store.js";
|
|
6
|
+
import { AccountPane } from "./panes/account.js";
|
|
7
|
+
import { AgentsPane } from "./panes/agents.js";
|
|
8
|
+
import { ChatPane } from "./panes/chat.js";
|
|
9
|
+
import { EnvironmentsPane } from "./panes/environments.js";
|
|
10
|
+
import { JobsPane } from "./panes/jobs.js";
|
|
11
|
+
import { ACCENT } from "./ui.js";
|
|
12
|
+
// The shell: tabs across the top, one pane, one line of hints at the bottom.
|
|
13
|
+
//
|
|
14
|
+
// The keyboard is arbitrated in exactly one place, here, on a rule simple
|
|
15
|
+
// enough to say in a sentence: whoever is deepest has it. An open overlay beats
|
|
16
|
+
// the pane, the chat's message field beats the shell, and everything else falls
|
|
17
|
+
// through to the tab keys. Panes ask for the keyboard by gating their own
|
|
18
|
+
// handlers on the flags this passes down, so there is no hidden precedence to
|
|
19
|
+
// go looking for when a keystroke lands somewhere surprising.
|
|
20
|
+
const TABS = ["environments", "agents", "jobs", "chat", "account"];
|
|
21
|
+
const HELP = `Getting around
|
|
22
|
+
|
|
23
|
+
tab / shift+tab next / previous section
|
|
24
|
+
1 to 5 jump straight to a section
|
|
25
|
+
up down j k move within a list
|
|
26
|
+
page up/down a screen at a time
|
|
27
|
+
g / G first / last
|
|
28
|
+
enter open what is selected
|
|
29
|
+
r refresh now
|
|
30
|
+
? this help
|
|
31
|
+
q or ctrl+c quit
|
|
32
|
+
|
|
33
|
+
Environments
|
|
34
|
+
n new R rename s resize c collaboration d destroy a its agents
|
|
35
|
+
|
|
36
|
+
Agents
|
|
37
|
+
n deploy m message R rename x run a command l logs d remove
|
|
38
|
+
f show only one environment's agents enter probe and diagnose
|
|
39
|
+
|
|
40
|
+
Jobs
|
|
41
|
+
enter steps w watch it run c cancel
|
|
42
|
+
|
|
43
|
+
Chat
|
|
44
|
+
a choose an agent enter send esc release the keyboard c clear
|
|
45
|
+
|
|
46
|
+
Everything here goes through the same control plane as the commands, with the
|
|
47
|
+
same credential and the same plan limits. Anything this cannot do yet, the
|
|
48
|
+
commands still can: quit and run "qoren --help".`;
|
|
49
|
+
function Shell() {
|
|
50
|
+
const { profile, profileName } = useSession();
|
|
51
|
+
const ui = useUi();
|
|
52
|
+
const { exit } = useApp();
|
|
53
|
+
const size = useWindowSize();
|
|
54
|
+
const [tab, setTab] = useState("environments");
|
|
55
|
+
const [environmentFilter, setEnvironmentFilter] = useState("");
|
|
56
|
+
const [chatAgent, setChatAgent] = useState(null);
|
|
57
|
+
const [chatTyping, setChatTyping] = useState(true);
|
|
58
|
+
const [reloadKey, setReloadKey] = useState(0);
|
|
59
|
+
// The chat field swallows letters while someone is writing, so the shell's
|
|
60
|
+
// own single-letter keys stand down until escape releases it.
|
|
61
|
+
const captured = tab === "chat" && chatAgent !== null && chatTyping;
|
|
62
|
+
const shellActive = !ui.busy && !captured;
|
|
63
|
+
useInput((input, key) => {
|
|
64
|
+
if (input === "q" || (key.ctrl && input === "c")) {
|
|
65
|
+
exit();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (input === "?") {
|
|
69
|
+
void ui.show("qoren", HELP);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (input === "r") {
|
|
73
|
+
// Remounting the pane is the honest way to refresh everything it
|
|
74
|
+
// holds, including any list it fetched for a picker.
|
|
75
|
+
setReloadKey((n) => n + 1);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const index = TABS.indexOf(tab);
|
|
79
|
+
if (key.tab) {
|
|
80
|
+
const step = key.shift ? -1 : 1;
|
|
81
|
+
setTab(TABS[(index + step + TABS.length) % TABS.length] ?? tab);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const digit = Number.parseInt(input, 10);
|
|
85
|
+
if (digit >= 1 && digit <= TABS.length) {
|
|
86
|
+
setTab(TABS[digit - 1] ?? tab);
|
|
87
|
+
}
|
|
88
|
+
}, { isActive: shellActive });
|
|
89
|
+
// Ctrl+C has to work even while the chat field has the keyboard: it is the
|
|
90
|
+
// one key nobody should have to press escape first to reach.
|
|
91
|
+
useInput((input, key) => {
|
|
92
|
+
if (key.ctrl && input === "c")
|
|
93
|
+
exit();
|
|
94
|
+
}, { isActive: !shellActive });
|
|
95
|
+
// Two rows of chrome above (title, tabs) and two below (hints, notice), plus
|
|
96
|
+
// the panel's own border and padding.
|
|
97
|
+
const paneHeight = Math.max(4, size.rows - 11);
|
|
98
|
+
const paneWidth = Math.max(40, size.columns - 4);
|
|
99
|
+
const pane = () => {
|
|
100
|
+
switch (tab) {
|
|
101
|
+
case "environments":
|
|
102
|
+
return (_jsx(EnvironmentsPane, { height: paneHeight, focused: !ui.busy, onOpenAgents: (id) => {
|
|
103
|
+
setEnvironmentFilter(id);
|
|
104
|
+
setTab("agents");
|
|
105
|
+
} }, `env-${reloadKey}`));
|
|
106
|
+
case "agents":
|
|
107
|
+
return (_jsx(AgentsPane, { height: paneHeight, focused: !ui.busy, environmentFilter: environmentFilter, onFilterChange: setEnvironmentFilter, onChat: (agent) => {
|
|
108
|
+
setChatAgent(agent);
|
|
109
|
+
setChatTyping(true);
|
|
110
|
+
setTab("chat");
|
|
111
|
+
} }, `agents-${reloadKey}`));
|
|
112
|
+
case "jobs":
|
|
113
|
+
return (_jsx(JobsPane, { height: paneHeight, focused: !ui.busy }, `jobs-${reloadKey}`));
|
|
114
|
+
case "chat":
|
|
115
|
+
return (_jsx(ChatPane, { height: paneHeight, width: paneWidth, focused: !ui.busy, agent: chatAgent, onPickAgent: (agent) => {
|
|
116
|
+
setChatAgent(agent);
|
|
117
|
+
setChatTyping(true);
|
|
118
|
+
}, typing: chatTyping, onTyping: setChatTyping }));
|
|
119
|
+
case "account":
|
|
120
|
+
return (_jsx(AccountPane, { height: paneHeight, focused: !ui.busy }, `account-${reloadKey}`));
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
return (_jsxs(Box, { flexDirection: "column", width: size.columns, children: [_jsxs(Box, { justifyContent: "space-between", paddingX: 1, children: [_jsx(Text, { bold: true, color: ACCENT, children: "qoren" }), _jsx(Text, { dimColor: true, children: `${profile.email ?? profileName} ${profile.baseUrl}` })] }), _jsx(Box, { paddingX: 1, children: TABS.map((name, i) => (_jsx(Text, { color: name === tab ? ACCENT : undefined, bold: name === tab, dimColor: name !== tab, children: `${i + 1} ${name} ` }, name))) }), _jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: ui.busy ? "gray" : ACCENT, paddingX: 1, minHeight: paneHeight + 4, children: ui.overlay ?? pane() }), _jsx(Box, { paddingX: 1, children: ui.notice ? (_jsx(Text, { color: ui.notice.tone === "bad" ? "red" : "green", wrap: "truncate-end", children: ui.notice.message })) : (_jsx(Text, { dimColor: true, children: captured
|
|
124
|
+
? "esc release the keyboard"
|
|
125
|
+
: "tab section r refresh ? help q quit" })) })] }));
|
|
126
|
+
}
|
|
127
|
+
export function App({ session }) {
|
|
128
|
+
return (_jsx(SessionProvider, { value: session, children: _jsx(UiProvider, { children: _jsx(Shell, {}) }) }));
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Context } from "../context.js";
|
|
2
|
+
export declare class NotATerminal extends Error {
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Take over the terminal until the reader quits.
|
|
6
|
+
*
|
|
7
|
+
* Refuses anywhere it cannot work rather than degrading: this needs a keyboard
|
|
8
|
+
* and a screen, and a half-drawn interface in a pipe or a CI log is worse than
|
|
9
|
+
* a sentence saying which command to use instead.
|
|
10
|
+
*/
|
|
11
|
+
export declare function runInteractive(session: Context): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAQ7C,qBAAa,YAAa,SAAQ,KAAK;CAAG;AAE1C;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBpE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { render } from "ink";
|
|
3
|
+
import { App } from "./app.js";
|
|
4
|
+
// Starting interactive mode.
|
|
5
|
+
//
|
|
6
|
+
// Kept apart from the React tree so nothing in src/tui runs on import: the
|
|
7
|
+
// command tree is built for every invocation, including `qoren env ls --json`
|
|
8
|
+
// in a cron job, and mounting a renderer there would be absurd.
|
|
9
|
+
export class NotATerminal extends Error {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Take over the terminal until the reader quits.
|
|
13
|
+
*
|
|
14
|
+
* Refuses anywhere it cannot work rather than degrading: this needs a keyboard
|
|
15
|
+
* and a screen, and a half-drawn interface in a pipe or a CI log is worse than
|
|
16
|
+
* a sentence saying which command to use instead.
|
|
17
|
+
*/
|
|
18
|
+
export async function runInteractive(session) {
|
|
19
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
20
|
+
throw new NotATerminal("Interactive mode needs a terminal. Use the commands instead: run `qoren --help`.");
|
|
21
|
+
}
|
|
22
|
+
const instance = render(_jsx(App, { session: session }), {
|
|
23
|
+
// The alternate screen, the way vim and less use it: this gets the whole
|
|
24
|
+
// window, and the reader's scrollback comes back untouched on quit.
|
|
25
|
+
alternateScreen: true,
|
|
26
|
+
// Ctrl+C is wired up in the shell so it can work while the chat field has
|
|
27
|
+
// the keyboard; letting Ink handle it too would be a second exit path with
|
|
28
|
+
// different teardown.
|
|
29
|
+
exitOnCtrlC: false,
|
|
30
|
+
incrementalRendering: true,
|
|
31
|
+
});
|
|
32
|
+
await instance.waitUntilExit();
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tui/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAG/B,6BAA6B;AAC7B,EAAE;AACF,2EAA2E;AAC3E,8EAA8E;AAC9E,gEAAgE;AAEhE,MAAM,OAAO,YAAa,SAAQ,KAAK;CAAG;AAE1C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAgB;IACnD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAClD,MAAM,IAAI,YAAY,CACpB,kFAAkF,CACnF,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAC,GAAG,IAAC,OAAO,EAAE,OAAO,GAAI,EAAE;QACjD,yEAAyE;QACzE,oEAAoE;QACpE,eAAe,EAAE,IAAI;QACrB,0EAA0E;QAC1E,2EAA2E;QAC3E,sBAAsB;QACtB,WAAW,EAAE,KAAK;QAClB,oBAAoB,EAAE,IAAI;KAC3B,CAAC,CAAC;IAEH,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { Job } from "@qoren/sdk";
|
|
2
|
+
import { type Tone } from "../output.js";
|
|
3
|
+
/** Ink colour for a lifecycle word. The vocabulary itself lives in output.ts,
|
|
4
|
+
* so the console and the plain tables agree on what "provisioning" means. */
|
|
5
|
+
export declare function toneColor(tone: Tone): string;
|
|
6
|
+
export declare const statusColorName: (status: string) => string;
|
|
7
|
+
/**
|
|
8
|
+
* Move a selection by `delta`, clamped to the list.
|
|
9
|
+
*
|
|
10
|
+
* Clamped rather than wrapping: in a list of thirty environments, holding the
|
|
11
|
+
* down arrow and silently landing back on the first one is disorienting, and
|
|
12
|
+
* there is no way to tell it apart from not having moved at all.
|
|
13
|
+
*/
|
|
14
|
+
export declare function moveSelection(count: number, current: number, delta: number): number;
|
|
15
|
+
/**
|
|
16
|
+
* The slice of a list to draw, given how many rows the pane has.
|
|
17
|
+
*
|
|
18
|
+
* The window only moves when the selection would leave it, so paging through a
|
|
19
|
+
* long list scrolls a line at a time instead of jumping by a screenful and
|
|
20
|
+
* losing the reader's place.
|
|
21
|
+
*/
|
|
22
|
+
export declare function scrollWindow(count: number, selected: number, height: number, previousStart?: number): {
|
|
23
|
+
start: number;
|
|
24
|
+
end: number;
|
|
25
|
+
};
|
|
26
|
+
export type LineState = {
|
|
27
|
+
value: string;
|
|
28
|
+
cursor: number;
|
|
29
|
+
};
|
|
30
|
+
export declare const emptyLine: (value?: string) => LineState;
|
|
31
|
+
/** The subset of Ink's Key that a text field cares about. */
|
|
32
|
+
export type EditKey = {
|
|
33
|
+
leftArrow?: boolean;
|
|
34
|
+
rightArrow?: boolean;
|
|
35
|
+
backspace?: boolean;
|
|
36
|
+
delete?: boolean;
|
|
37
|
+
home?: boolean;
|
|
38
|
+
end?: boolean;
|
|
39
|
+
ctrl?: boolean;
|
|
40
|
+
meta?: boolean;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Apply one keystroke to a text field.
|
|
44
|
+
*
|
|
45
|
+
* Written as a reducer so the editing rules — including the readline habits
|
|
46
|
+
* people's fingers already know (ctrl+a/e/u/k/w) — can be tested without a
|
|
47
|
+
* terminal. Returns the state unchanged when the keystroke means nothing here.
|
|
48
|
+
*
|
|
49
|
+
* Note on backspace: some terminals report the backspace key as `delete` with
|
|
50
|
+
* no `backspace` flag, so a `delete` at the end of the line rubs out to the
|
|
51
|
+
* left rather than doing nothing at all.
|
|
52
|
+
*/
|
|
53
|
+
export declare function editLine(state: LineState, input: string, key: EditKey): LineState;
|
|
54
|
+
export type ChatTurn = {
|
|
55
|
+
/** What the agent has said so far. Grows while the turn streams. */
|
|
56
|
+
text: string;
|
|
57
|
+
/** Still arriving, so the console should keep showing it as in progress. */
|
|
58
|
+
streaming: boolean;
|
|
59
|
+
/** The tool the agent is running right now, when it is running one. */
|
|
60
|
+
tool: string | null;
|
|
61
|
+
/** The conversation to resume next message, when the harness gave one. */
|
|
62
|
+
sessionId: string | null;
|
|
63
|
+
stdErr: string;
|
|
64
|
+
exitCode: number | null;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Read a message job's result.
|
|
68
|
+
*
|
|
69
|
+
* The control plane writes the reply into the job's result as it arrives — a
|
|
70
|
+
* partial snapshot flagged `streaming` a few times a second, then the final
|
|
71
|
+
* one — so polling the job is how the console shows an agent thinking out loud
|
|
72
|
+
* instead of staring at a spinner for two minutes.
|
|
73
|
+
*
|
|
74
|
+
* Read defensively: this is a `Record<string, unknown>` on the wire, and a turn
|
|
75
|
+
* that fell back to the SSH path carries no session id at all.
|
|
76
|
+
*/
|
|
77
|
+
export declare function readChatTurn(result: unknown): ChatTurn;
|
|
78
|
+
/**
|
|
79
|
+
* How long to wait before refreshing a pane, in milliseconds.
|
|
80
|
+
*
|
|
81
|
+
* A fleet at rest changes on the scale of minutes and every poll is a real
|
|
82
|
+
* request against someone's control plane, so the idle cadence is deliberately
|
|
83
|
+
* slow. Anything mid-flight — provisioning, deploying, a running job — is worth
|
|
84
|
+
* watching closely, and only then does the console poll hard.
|
|
85
|
+
*/
|
|
86
|
+
export declare function refreshDelay(statuses: string[], idleMs?: number, activeMs?: number): number;
|
|
87
|
+
/** Step completion for a job row, e.g. "9/12". Mirrors jobProgress.jobSummary. */
|
|
88
|
+
export declare function jobProgressText(job: Job): string;
|
|
89
|
+
/** The step a job is on right now, for a one-line summary. */
|
|
90
|
+
export declare function currentStep(job: Job): string;
|
|
91
|
+
/**
|
|
92
|
+
* Break text into lines that fit `width`, keeping the newlines it already has.
|
|
93
|
+
*
|
|
94
|
+
* The chat transcript needs to know how many lines a reply actually occupies
|
|
95
|
+
* before it can decide how much of the conversation still fits on screen, and
|
|
96
|
+
* asking the renderer after the fact is too late. Words longer than the width
|
|
97
|
+
* (a URL, a stack frame) are split rather than allowed to overflow.
|
|
98
|
+
*/
|
|
99
|
+
export declare function wrapText(text: string, width: number): string[];
|
|
100
|
+
/**
|
|
101
|
+
* A date someone can read, from whatever the wire sent.
|
|
102
|
+
*
|
|
103
|
+
* Timestamps arrive as ISO strings in some places and epoch millis in others
|
|
104
|
+
* (the usage governor's period bounds among them), and "1786150711602" is not
|
|
105
|
+
* an answer to "when does my billing period end".
|
|
106
|
+
*/
|
|
107
|
+
export declare function readableDate(value: string | number | null | undefined): string;
|
|
108
|
+
/** Fit text to a column, with an ellipsis when it does not. */
|
|
109
|
+
export declare function truncate(text: string, width: number): string;
|
|
110
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/tui/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAUrD;6EAC6E;AAC7E,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAW5C;AAED,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,KAAG,MAClB,CAAC;AAEhC;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,CAGR;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,aAAa,SAAI,GAChB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAOhC;AAID,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,eAAO,MAAM,SAAS,GAAI,cAAU,KAAG,SAGrC,CAAC;AAEH,6DAA6D;AAC7D,MAAM,MAAM,OAAO,GAAG;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAOF;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,OAAO,GACX,SAAS,CAwDX;AAID,MAAM,MAAM,QAAQ,GAAG;IACrB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAaF;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAYtD;AAMD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAAE,EAClB,MAAM,SAAS,EACf,QAAQ,SAAQ,GACf,MAAM,CAKR;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAIhD;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAK5C;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA4B9D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAK9E;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAI5D"}
|