@jinion/cli 0.0.0-stage → 0.4.524
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/CHANGELOG.md +249 -0
- package/bin/jinion.js +15 -0
- package/dist/app/activity.js +50 -0
- package/dist/app/activity.js.map +1 -0
- package/dist/app/announcements.js +21 -0
- package/dist/app/announcements.js.map +1 -0
- package/dist/app/api.js +26 -0
- package/dist/app/api.js.map +1 -0
- package/dist/app/app.js +99 -0
- package/dist/app/app.js.map +1 -0
- package/dist/app/aside.js +52 -0
- package/dist/app/aside.js.map +1 -0
- package/dist/app/claude-notes.js +19 -0
- package/dist/app/claude-notes.js.map +1 -0
- package/dist/app/dialogs.js +43 -0
- package/dist/app/dialogs.js.map +1 -0
- package/dist/app/keys.js +79 -0
- package/dist/app/keys.js.map +1 -0
- package/dist/app/prompt-area.js +56 -0
- package/dist/app/prompt-area.js.map +1 -0
- package/dist/app/release-notes.js +20 -0
- package/dist/app/release-notes.js.map +1 -0
- package/dist/app/settings-file.js +7 -0
- package/dist/app/settings-file.js.map +1 -0
- package/dist/app/shortcuts.js +31 -0
- package/dist/app/shortcuts.js.map +1 -0
- package/dist/app/sidebar.js +50 -0
- package/dist/app/sidebar.js.map +1 -0
- package/dist/app/status-line.js +29 -0
- package/dist/app/status-line.js.map +1 -0
- package/dist/app/task-line.js +19 -0
- package/dist/app/task-line.js.map +1 -0
- package/dist/app/updates.js +17 -0
- package/dist/app/updates.js.map +1 -0
- package/dist/app/use-screen.js +24 -0
- package/dist/app/use-screen.js.map +1 -0
- package/dist/app/views.js +68 -0
- package/dist/app/views.js.map +1 -0
- package/dist/main.js +124 -0
- package/dist/main.js.map +1 -0
- package/dist/panels/account/account-picker.js +118 -0
- package/dist/panels/account/account-picker.js.map +1 -0
- package/dist/panels/account/describe.js +14 -0
- package/dist/panels/account/describe.js.map +1 -0
- package/dist/panels/account/sign-in-view.js +8 -0
- package/dist/panels/account/sign-in-view.js.map +1 -0
- package/dist/panels/account/use-sign-in.js +46 -0
- package/dist/panels/account/use-sign-in.js.map +1 -0
- package/dist/panels/context.js +55 -0
- package/dist/panels/context.js.map +1 -0
- package/dist/panels/diff/change-list.js +48 -0
- package/dist/panels/diff/change-list.js.map +1 -0
- package/dist/panels/diff/current-view.js +47 -0
- package/dist/panels/diff/current-view.js.map +1 -0
- package/dist/panels/diff/diff-panel.js +22 -0
- package/dist/panels/diff/diff-panel.js.map +1 -0
- package/dist/panels/diff/file-diff.js +19 -0
- package/dist/panels/diff/file-diff.js.map +1 -0
- package/dist/panels/diff/views.js +29 -0
- package/dist/panels/diff/views.js.map +1 -0
- package/dist/panels/feedback.js +67 -0
- package/dist/panels/feedback.js.map +1 -0
- package/dist/panels/help.js +79 -0
- package/dist/panels/help.js.map +1 -0
- package/dist/panels/map.js +80 -0
- package/dist/panels/map.js.map +1 -0
- package/dist/panels/mcp.js +129 -0
- package/dist/panels/mcp.js.map +1 -0
- package/dist/panels/memory.js +55 -0
- package/dist/panels/memory.js.map +1 -0
- package/dist/panels/mode.js +36 -0
- package/dist/panels/mode.js.map +1 -0
- package/dist/panels/model.js +20 -0
- package/dist/panels/model.js.map +1 -0
- package/dist/panels/onboarding/claude-setup-panel.js +68 -0
- package/dist/panels/onboarding/claude-setup-panel.js.map +1 -0
- package/dist/panels/onboarding/onboarding-panel.js +56 -0
- package/dist/panels/onboarding/onboarding-panel.js.map +1 -0
- package/dist/panels/onboarding/use-onboarding.js +65 -0
- package/dist/panels/onboarding/use-onboarding.js.map +1 -0
- package/dist/panels/profile.js +31 -0
- package/dist/panels/profile.js.map +1 -0
- package/dist/panels/release-notes.js +60 -0
- package/dist/panels/release-notes.js.map +1 -0
- package/dist/panels/resume.js +52 -0
- package/dist/panels/resume.js.map +1 -0
- package/dist/panels/rewind/changes.js +20 -0
- package/dist/panels/rewind/changes.js.map +1 -0
- package/dist/panels/rewind/rewind-panel.js +93 -0
- package/dist/panels/rewind/rewind-panel.js.map +1 -0
- package/dist/panels/sign-in/sign-in-panel.js +56 -0
- package/dist/panels/sign-in/sign-in-panel.js.map +1 -0
- package/dist/panels/sign-in/use-jinion-sign-in.js +69 -0
- package/dist/panels/sign-in/use-jinion-sign-in.js.map +1 -0
- package/dist/panels/statusline.js +94 -0
- package/dist/panels/statusline.js.map +1 -0
- package/dist/panels/tasks/output.js +23 -0
- package/dist/panels/tasks/output.js.map +1 -0
- package/dist/panels/tasks/task-output.js +29 -0
- package/dist/panels/tasks/task-output.js.map +1 -0
- package/dist/panels/tasks/tasks-panel.js +75 -0
- package/dist/panels/tasks/tasks-panel.js.map +1 -0
- package/dist/panels/terminal-setup.js +41 -0
- package/dist/panels/terminal-setup.js.map +1 -0
- package/dist/panels/usage/section.js +16 -0
- package/dist/panels/usage/section.js.map +1 -0
- package/dist/panels/usage/stats-view.js +52 -0
- package/dist/panels/usage/stats-view.js.map +1 -0
- package/dist/panels/usage/usage-panel.js +68 -0
- package/dist/panels/usage/usage-panel.js.map +1 -0
- package/dist/panels/usage/usage-view.js +51 -0
- package/dist/panels/usage/usage-view.js.map +1 -0
- package/dist/prompt/attachments.js +91 -0
- package/dist/prompt/attachments.js.map +1 -0
- package/dist/prompt/draft.js +24 -0
- package/dist/prompt/draft.js.map +1 -0
- package/dist/prompt/images.js +84 -0
- package/dist/prompt/images.js.map +1 -0
- package/dist/prompt/pasted-path.js +19 -0
- package/dist/prompt/pasted-path.js.map +1 -0
- package/dist/prompt/use-prompt.js +62 -0
- package/dist/prompt/use-prompt.js.map +1 -0
- package/dist/serve.js +38 -0
- package/dist/serve.js.map +1 -0
- package/dist/state/session.js +93 -0
- package/dist/state/session.js.map +1 -0
- package/dist/status/data.js +39 -0
- package/dist/status/data.js.map +1 -0
- package/dist/status/git.js +18 -0
- package/dist/status/git.js.map +1 -0
- package/dist/status/items.js +8 -0
- package/dist/status/items.js.map +1 -0
- package/dist/status/line.js +25 -0
- package/dist/status/line.js.map +1 -0
- package/dist/status/saved.js +8 -0
- package/dist/status/saved.js.map +1 -0
- package/dist/status/segment.js +2 -0
- package/dist/status/segment.js.map +1 -0
- package/dist/status/segments/conversation.js +71 -0
- package/dist/status/segments/conversation.js.map +1 -0
- package/dist/status/segments/git.js +33 -0
- package/dist/status/segments/git.js.map +1 -0
- package/dist/status/segments/identity.js +71 -0
- package/dist/status/segments/identity.js.map +1 -0
- package/dist/status/segments/index.js +27 -0
- package/dist/status/segments/index.js.map +1 -0
- package/dist/status/segments/usage.js +61 -0
- package/dist/status/segments/usage.js.map +1 -0
- package/dist/terminal/apple-terminal.js +65 -0
- package/dist/terminal/apple-terminal.js.map +1 -0
- package/dist/ui/banner.js +36 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/entries/changes-card.js +27 -0
- package/dist/ui/entries/changes-card.js.map +1 -0
- package/dist/ui/entries/entry-view.js +82 -0
- package/dist/ui/entries/entry-view.js.map +1 -0
- package/dist/ui/entries/status-entries.js +33 -0
- package/dist/ui/entries/status-entries.js.map +1 -0
- package/dist/ui/entries/tools/agent-view.js +39 -0
- package/dist/ui/entries/tools/agent-view.js.map +1 -0
- package/dist/ui/entries/tools/mcp-view.js +10 -0
- package/dist/ui/entries/tools/mcp-view.js.map +1 -0
- package/dist/ui/entries/tools/result-preview.js +19 -0
- package/dist/ui/entries/tools/result-preview.js.map +1 -0
- package/dist/ui/entries/tools/search.js +42 -0
- package/dist/ui/entries/tools/search.js.map +1 -0
- package/dist/ui/entries/tools/shell-footer.js +36 -0
- package/dist/ui/entries/tools/shell-footer.js.map +1 -0
- package/dist/ui/entries/tools/tool-view.js +47 -0
- package/dist/ui/entries/tools/tool-view.js.map +1 -0
- package/dist/ui/entries/tools/web.js +41 -0
- package/dist/ui/entries/tools/web.js.map +1 -0
- package/dist/ui/modes.js +13 -0
- package/dist/ui/modes.js.map +1 -0
- package/dist/ui/task-marks.js +7 -0
- package/dist/ui/task-marks.js.map +1 -0
- package/dist/ui/use-async.js +17 -0
- package/dist/ui/use-async.js.map +1 -0
- package/dist/ui/use-map-overview.js +27 -0
- package/dist/ui/use-map-overview.js.map +1 -0
- package/dist/ui/use-pager.js +25 -0
- package/dist/ui/use-pager.js.map +1 -0
- package/dist/ui/use-project-files.js +18 -0
- package/dist/ui/use-project-files.js.map +1 -0
- package/dist/ui/use-workdir.js +9 -0
- package/dist/ui/use-workdir.js.map +1 -0
- package/dist/update/updater.js +68 -0
- package/dist/update/updater.js.map +1 -0
- package/dist/update/versions.js +31 -0
- package/dist/update/versions.js.map +1 -0
- package/package.json +35 -3
- package/README.md +0 -3
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { ChoiceList, Panel, Text, useChoiceList, useInput, usePanel, useTheme } from '@jinion/tui';
|
|
4
|
+
import { useAtom, useSetAtom } from 'jotai';
|
|
5
|
+
import { statusItemsAtom, statusPreviewAtom } from '../status/items.js';
|
|
6
|
+
import { useStatusData } from '../status/data.js';
|
|
7
|
+
import { DEFAULT_STATUS_LINE, styleOf } from '../status/line.js';
|
|
8
|
+
import { findSegment, SEGMENTS } from '../status/segments/index.js';
|
|
9
|
+
const VISIBLE = 6;
|
|
10
|
+
const NAME_WIDTH = 13;
|
|
11
|
+
export function StatusLinePanel() {
|
|
12
|
+
const theme = useTheme();
|
|
13
|
+
const { close } = usePanel();
|
|
14
|
+
const data = useStatusData();
|
|
15
|
+
const [saved, save] = useAtom(statusItemsAtom);
|
|
16
|
+
const preview = useSetAtom(statusPreviewAtom);
|
|
17
|
+
const [order, setOrder] = useState(() => orderOf(saved));
|
|
18
|
+
const [looks, setLooks] = useState(() => looksOf(saved));
|
|
19
|
+
const itemsOf = (checked) => order.filter((id) => checked.includes(id)).map((id) => ({ id, ...looks[id] }));
|
|
20
|
+
const list = useChoiceList({
|
|
21
|
+
keys: order,
|
|
22
|
+
mode: 'multiple',
|
|
23
|
+
initialChecked: saved.map((item) => item.id),
|
|
24
|
+
onCancel: close,
|
|
25
|
+
onSubmit: (checked) => {
|
|
26
|
+
save(itemsOf(checked));
|
|
27
|
+
close();
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const draft = itemsOf(list.checked);
|
|
31
|
+
const draftKey = JSON.stringify(draft);
|
|
32
|
+
const choices = order.map((id) => {
|
|
33
|
+
const segment = findSegment(id);
|
|
34
|
+
const look = looks[id];
|
|
35
|
+
const shown = list.isChecked(id);
|
|
36
|
+
const style = styleOf({ id, ...look });
|
|
37
|
+
const sample = segment.render(data, style);
|
|
38
|
+
return {
|
|
39
|
+
key: id,
|
|
40
|
+
label: (_jsxs(Text, { children: [segment.name.padEnd(NAME_WIDTH), _jsx(Text, { dimColor: !shown, children: sample ?? _jsx(Text, { color: theme.muted, children: "nothing to show yet" }) })] })),
|
|
41
|
+
description: [segment.description, segment.styles?.find((candidate) => candidate.id === style)?.name].filter(Boolean).join(' · '),
|
|
42
|
+
aside: shown ? look.side : undefined,
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
useEffect(() => preview(draft), [draftKey]);
|
|
46
|
+
// However the panel closes, the line goes back to what is saved.
|
|
47
|
+
useEffect(() => () => preview(undefined), []);
|
|
48
|
+
useInput((input, key) => {
|
|
49
|
+
const id = list.focus;
|
|
50
|
+
const look = looks[id];
|
|
51
|
+
const styles = findSegment(id)?.styles ?? [];
|
|
52
|
+
const restyle = (next) => setLooks({ ...looks, [id]: { ...look, ...next } });
|
|
53
|
+
if ((key.upArrow || key.downArrow) && key.shift) {
|
|
54
|
+
const index = order.indexOf(id);
|
|
55
|
+
const target = index + (key.upArrow ? -1 : 1);
|
|
56
|
+
if (target < 0 || target >= order.length)
|
|
57
|
+
return;
|
|
58
|
+
const moved = [...order];
|
|
59
|
+
moved[index] = moved[target];
|
|
60
|
+
moved[target] = id;
|
|
61
|
+
return setOrder(moved);
|
|
62
|
+
}
|
|
63
|
+
if (key.tab)
|
|
64
|
+
return restyle({ side: look.side === 'left' ? 'right' : 'left' });
|
|
65
|
+
if ((key.leftArrow || key.rightArrow) && styles.length > 1) {
|
|
66
|
+
const index = styles.findIndex((style) => style.id === styleOf({ id, ...look }));
|
|
67
|
+
return restyle({ style: styles[(index + (key.rightArrow ? 1 : -1) + styles.length) % styles.length].id });
|
|
68
|
+
}
|
|
69
|
+
if (input === 'r') {
|
|
70
|
+
setOrder(orderOf(DEFAULT_STATUS_LINE));
|
|
71
|
+
setLooks(looksOf(DEFAULT_STATUS_LINE));
|
|
72
|
+
for (const segment of SEGMENTS)
|
|
73
|
+
list.setChecked(segment.id, DEFAULT_STATUS_LINE.some((item) => item.id === segment.id));
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return (_jsx(Panel, { title: "Status line", subtitle: `${list.checked.length} of ${SEGMENTS.length} shown`, header: _jsx(Text, { color: theme.muted, children: "Checked items show in the status line below, in this order. Changes show as you make them." }), hints: [
|
|
77
|
+
['Space', 'select'],
|
|
78
|
+
['Shift+Up/Down', 'move'],
|
|
79
|
+
['Tab', 'side'],
|
|
80
|
+
['Left/Right', 'style'],
|
|
81
|
+
['r', 'reset'],
|
|
82
|
+
['Enter', 'save'],
|
|
83
|
+
['Esc', 'cancel'],
|
|
84
|
+
], children: _jsx(ChoiceList, { list: list, choices: choices, limit: VISIBLE }) }));
|
|
85
|
+
}
|
|
86
|
+
const orderOf = (items) => [
|
|
87
|
+
...items.map((item) => item.id),
|
|
88
|
+
...SEGMENTS.filter((segment) => !items.some((item) => item.id === segment.id)).map((segment) => segment.id),
|
|
89
|
+
];
|
|
90
|
+
const looksOf = (items) => Object.fromEntries(SEGMENTS.map((segment) => {
|
|
91
|
+
const item = items.find((candidate) => candidate.id === segment.id);
|
|
92
|
+
return [segment.id, item ? { side: item.side, style: item.style } : { side: 'left' }];
|
|
93
|
+
}));
|
|
94
|
+
//# sourceMappingURL=statusline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statusline.js","sourceRoot":"","sources":["../../src/panels/statusline.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { printable } from '@jinion/tui';
|
|
3
|
+
import { useApi } from '../../app/api.js';
|
|
4
|
+
const POLL_MS = 500;
|
|
5
|
+
/** The end of what task `id` wrote, read again while it runs; nothing for a task that writes none. */
|
|
6
|
+
export function useOutput(id, live) {
|
|
7
|
+
const api = useApi();
|
|
8
|
+
const [lines, setLines] = useState();
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
if (id === undefined)
|
|
11
|
+
return;
|
|
12
|
+
let open = true;
|
|
13
|
+
const read = () => api.inSession('session/task-output', { task: id }).then((tail) => open && tail && setLines(printable(tail.join('\n')).split('\n')), () => { });
|
|
14
|
+
void read();
|
|
15
|
+
const timer = live ? setInterval(read, POLL_MS) : undefined;
|
|
16
|
+
return () => {
|
|
17
|
+
open = false;
|
|
18
|
+
clearInterval(timer);
|
|
19
|
+
};
|
|
20
|
+
}, [id, live]);
|
|
21
|
+
return lines;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/panels/tasks/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,OAAO,GAAG,GAAG,CAAC;AAEpB,sGAAsG;AACtG,MAAM,UAAU,SAAS,CAAC,EAAsB,EAAE,IAAa;IAC7D,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;IAErB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,EAAY,CAAC;IAE/C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO;QAE7B,IAAI,IAAI,GAAG,IAAI,CAAC;QAEhB,MAAM,IAAI,GAAG,GAAG,EAAE,CAChB,GAAG,CAAC,SAAS,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CACrD,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,IAAI,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAC1E,GAAG,EAAE,GAAE,CAAC,CACT,CAAC;QAEJ,KAAK,IAAI,EAAE,CAAC;QAEZ,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE5D,OAAO,GAAG,EAAE;YACV,IAAI,GAAG,KAAK,CAAC;YACb,aAAa,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;IAEf,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Panel, printable, Text, useInput, usePanel, useTheme } from '@jinion/tui';
|
|
3
|
+
import { useAtomValue } from 'jotai';
|
|
4
|
+
import { useApi } from '../../app/api.js';
|
|
5
|
+
import { tasksAtom } from '../../state/session.js';
|
|
6
|
+
import { firstLine } from '@jinion/core/lib/text';
|
|
7
|
+
import { PAGER_HINTS, usePager } from '../../ui/use-pager.js';
|
|
8
|
+
import { useOutput } from './output.js';
|
|
9
|
+
const CHROME_ROWS = 6;
|
|
10
|
+
export function TaskOutput({ id }) {
|
|
11
|
+
const api = useApi();
|
|
12
|
+
const theme = useTheme();
|
|
13
|
+
const { close } = usePanel();
|
|
14
|
+
const task = useAtomValue(tasksAtom).find((candidate) => candidate.id === id);
|
|
15
|
+
const lines = useOutput(id, task?.status === 'running') ?? [];
|
|
16
|
+
const pager = usePager(lines.length, { chrome: CHROME_ROWS, follow: true });
|
|
17
|
+
useInput((input, key) => {
|
|
18
|
+
if (key.escape)
|
|
19
|
+
return close();
|
|
20
|
+
if (input === 'x' && task?.status === 'running')
|
|
21
|
+
return api.act(api.inSession('session/stop-task', { task: task.id }));
|
|
22
|
+
pager.scroll(key);
|
|
23
|
+
});
|
|
24
|
+
if (!task)
|
|
25
|
+
return null;
|
|
26
|
+
const hints = [...PAGER_HINTS, ...(task.status === 'running' ? [['x', 'stop']] : []), ['Esc', 'back']];
|
|
27
|
+
return (_jsx(Panel, { title: "Output", subtitle: [printable(firstLine(task.title)), pager.range].filter(Boolean).join(' · '), grow: true, hints: hints, children: lines.length === 0 ? (_jsx(Text, { color: theme.muted, children: "No output yet." })) : (lines.slice(pager.top, pager.top + pager.view).map((line, index) => (_jsx(Text, { wrap: "truncate-end", children: line || ' ' }, pager.top + index)))) }));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=task-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-output.js","sourceRoot":"","sources":["../../../src/panels/tasks/task-output.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, ChoiceList, choiceIndent, Panel, printable, StatusMark, Text, useAnimation, useChoiceList, useInput, usePanel, usePanels, useTheme, } from '@jinion/tui';
|
|
3
|
+
import { useAtomValue } from 'jotai';
|
|
4
|
+
import { backgroundTasksAtom } from '../../state/session.js';
|
|
5
|
+
import { useApi } from '../../app/api.js';
|
|
6
|
+
import { elapsed, plural } from '@jinion/core/lib/format';
|
|
7
|
+
import { firstLine } from '@jinion/core/lib/text';
|
|
8
|
+
import { TASK_MARKS } from '../../ui/task-marks.js';
|
|
9
|
+
import { useOutput } from './output.js';
|
|
10
|
+
import { TaskOutput } from './task-output.js';
|
|
11
|
+
const VISIBLE = 8;
|
|
12
|
+
const TAIL_LINES = 6;
|
|
13
|
+
export function TasksPanel() {
|
|
14
|
+
const api = useApi();
|
|
15
|
+
const theme = useTheme();
|
|
16
|
+
const { close } = usePanel();
|
|
17
|
+
const panels = usePanels();
|
|
18
|
+
const tasks = useAtomValue(backgroundTasksAtom);
|
|
19
|
+
useAnimation({ interval: 1000 });
|
|
20
|
+
const list = useChoiceList({
|
|
21
|
+
keys: tasks.map((task) => task.id),
|
|
22
|
+
mode: 'single',
|
|
23
|
+
onCancel: close,
|
|
24
|
+
onSubmit: ([id]) => {
|
|
25
|
+
const task = tasks.find((candidate) => candidate.id === id);
|
|
26
|
+
if (task?.output)
|
|
27
|
+
panels.open({ id: 'task-output', placement: 'fullscreen', element: _jsx(TaskOutput, { id: task.id }) });
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const focused = tasks.find((task) => task.id === list.focus);
|
|
31
|
+
const choices = tasks.map((task) => ({
|
|
32
|
+
key: task.id,
|
|
33
|
+
label: (_jsxs(Text, { wrap: "truncate-end", children: [_jsx(StatusMark, { status: TASK_MARKS[task.status] }), " ", task.kind === 'agent' && _jsx(Text, { color: theme.muted, children: "Agent \u00B7 " }), printable(firstLine(task.title))] })),
|
|
34
|
+
aside: _jsx(TaskTime, { task: task }),
|
|
35
|
+
editor: _jsx(TaskDetails, { task: task, indent: choiceIndent(list) }),
|
|
36
|
+
}));
|
|
37
|
+
const hints = [
|
|
38
|
+
...(focused?.output ? [['Enter', 'output']] : []),
|
|
39
|
+
...(focused?.status === 'running' ? [['x', 'stop']] : []),
|
|
40
|
+
['Up/Down', 'move'],
|
|
41
|
+
['Esc', 'close'],
|
|
42
|
+
];
|
|
43
|
+
const running = tasks.filter((task) => task.status === 'running').length;
|
|
44
|
+
useInput((input) => {
|
|
45
|
+
if (input === 'x' && focused?.status === 'running')
|
|
46
|
+
api.act(api.inSession('session/stop-task', { task: focused.id }));
|
|
47
|
+
});
|
|
48
|
+
return (_jsx(Panel, { title: "Background tasks", subtitle: tasks.length > 0 ? `${running} running` : undefined, hints: hints, children: _jsx(ChoiceList, { list: list, choices: choices, limit: VISIBLE, empty: "Nothing runs in the background. The agent starts commands there that keep running, like a dev server, and ctrl+b sends the command it waits for there." }) }));
|
|
49
|
+
}
|
|
50
|
+
function TaskTime({ task }) {
|
|
51
|
+
const theme = useTheme();
|
|
52
|
+
const took = elapsed((task.endedAt ?? Date.now()) - task.startedAt);
|
|
53
|
+
switch (task.status) {
|
|
54
|
+
case 'running':
|
|
55
|
+
return _jsx(Text, { color: theme.muted, children: took });
|
|
56
|
+
case 'completed':
|
|
57
|
+
return _jsxs(Text, { color: theme.muted, children: ["done in ", took] });
|
|
58
|
+
case 'failed':
|
|
59
|
+
return _jsxs(Text, { color: theme.error, children: ["failed after ", took] });
|
|
60
|
+
case 'stopped':
|
|
61
|
+
return _jsxs(Text, { color: theme.muted, children: ["stopped after ", took] });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function TaskDetails({ task, indent }) {
|
|
65
|
+
const theme = useTheme();
|
|
66
|
+
const lines = useOutput(task.output === undefined ? undefined : task.id, task.status === 'running');
|
|
67
|
+
if (task.kind === 'agent') {
|
|
68
|
+
return (_jsx(Box, { paddingLeft: indent, marginBottom: 1, children: _jsxs(Text, { color: theme.muted, wrap: "truncate-end", children: [plural(task.calls ?? 0, 'tool call'), task.lastCall && ` · ${task.lastCall}`] }) }));
|
|
69
|
+
}
|
|
70
|
+
if (!task.output)
|
|
71
|
+
return null;
|
|
72
|
+
const tail = lines?.slice(-TAIL_LINES) ?? [];
|
|
73
|
+
return (_jsx(Box, { flexDirection: "column", paddingLeft: indent, marginBottom: 1, children: tail.length === 0 ? (_jsx(Text, { color: theme.muted, children: lines ? 'No output yet.' : 'Reading the output…' })) : (tail.map((line, index) => (_jsx(Text, { color: theme.muted, wrap: "truncate-end", children: line || ' ' }, index)))) }));
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=tasks-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks-panel.js","sourceRoot":"","sources":["../../../src/panels/tasks/tasks-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import { ChoiceList, Panel, Text, useChoiceList, useInput, usePanel, useTheme } from '@jinion/tui';
|
|
4
|
+
import { errorMessage } from '@jinion/core/lib/errors';
|
|
5
|
+
import { useApi } from '../app/api.js';
|
|
6
|
+
import { inAppleTerminal, profilesWithoutMeta, rememberTerminalSetupOffered, turnOnOptionAsMeta } from '../terminal/apple-terminal.js';
|
|
7
|
+
import { useAsync } from '../ui/use-async.js';
|
|
8
|
+
const CHOICES = ['turn-on', 'not-now'];
|
|
9
|
+
export function TerminalSetupPanel() {
|
|
10
|
+
const api = useApi();
|
|
11
|
+
const theme = useTheme();
|
|
12
|
+
const { close } = usePanel();
|
|
13
|
+
const apple = inAppleTerminal();
|
|
14
|
+
const off = useAsync(() => (apple ? profilesWithoutMeta() : Promise.resolve([])), []);
|
|
15
|
+
const asking = off.state === 'done' && off.value.length > 0;
|
|
16
|
+
const list = useChoiceList({
|
|
17
|
+
keys: CHOICES,
|
|
18
|
+
mode: 'single',
|
|
19
|
+
isActive: asking,
|
|
20
|
+
onCancel: close,
|
|
21
|
+
onSubmit: ([choice]) => {
|
|
22
|
+
close();
|
|
23
|
+
if (choice !== 'turn-on')
|
|
24
|
+
return;
|
|
25
|
+
const notice = (text, tone) => api.act(api.inSession('session/notice', { text, tone }));
|
|
26
|
+
turnOnOptionAsMeta().then(() => notice('Done. Open a new Terminal window and Option+Delete will delete whole words.', 'muted'), (error) => notice(`Couldn’t update Terminal’s settings: ${errorMessage(error)}`, 'warning'));
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
// However it ends, it is offered once.
|
|
30
|
+
useEffect(() => rememberTerminalSetupOffered(), []);
|
|
31
|
+
useInput((_, key) => {
|
|
32
|
+
if (key.escape)
|
|
33
|
+
close();
|
|
34
|
+
}, { isActive: !asking });
|
|
35
|
+
const hints = asking ? [['Enter', 'continue'], ['Up/Down', 'move'], ['Esc', 'not now']] : [['Esc', 'close']];
|
|
36
|
+
return (_jsx(Panel, { title: "Terminal setup", subtitle: apple ? 'Terminal' : undefined, hints: hints, children: !apple ? (_jsx(Text, { color: theme.muted, children: "This only works in Terminal.app. In iTerm2, go to Settings \u2192 Profiles \u2192 Keys and set Left Option key to Esc+." })) : off.state === 'pending' ? (_jsx(Text, { color: theme.muted, children: "Checking your Terminal settings\u2026" })) : off.state === 'failed' ? (_jsxs(Text, { color: theme.error, children: ["Couldn\u2019t read your Terminal settings: ", off.error] })) : off.value.length === 0 ? (_jsx(Text, { color: theme.muted, children: "You\u2019re all set. Option+Delete already deletes whole words." })) : (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.muted, children: "In Terminal, Option+Delete only deletes one character. Jinion can turn on \u201CUse Option as Meta key\u201D for you so it deletes whole words, like everywhere else on your Mac. Option won\u2019t type special characters like \u00A9 in Terminal after that." }), _jsx(ChoiceList, { list: list, limit: CHOICES.length, choices: [
|
|
37
|
+
{ key: 'turn-on', label: _jsx(Text, { children: "Turn it on" }) },
|
|
38
|
+
{ key: 'not-now', label: _jsx(Text, { children: "Not now" }), description: 'You can do this later with /terminal-setup' },
|
|
39
|
+
] })] })) }));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=terminal-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-setup.js","sourceRoot":"","sources":["../../src/panels/terminal-setup.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useTheme } from '@jinion/tui';
|
|
3
|
+
import { compact } from '@jinion/core/lib/format';
|
|
4
|
+
export function Section({ title, aside, children }) {
|
|
5
|
+
const theme = useTheme();
|
|
6
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { bold: true, children: title }), aside && _jsxs(Text, { color: theme.muted, children: [" ", aside] })] }), children] }));
|
|
7
|
+
}
|
|
8
|
+
export function tokenLine(tokens) {
|
|
9
|
+
const parts = [`${compact(tokens.input)} in`, `${compact(tokens.output)} out`, `${compact(tokens.cacheRead)} cache read`, `${compact(tokens.cacheWrite)} cache write`];
|
|
10
|
+
const split = tokens.input + tokens.output + tokens.cacheRead + tokens.cacheWrite;
|
|
11
|
+
if (!tokens.summarized)
|
|
12
|
+
return parts.join(' · ');
|
|
13
|
+
const summarized = `${compact(tokens.summarized)} from a summary of older days`;
|
|
14
|
+
return split > 0 ? `${parts.join(' · ')} · ${summarized}` : summarized;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=section.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section.js","sourceRoot":"","sources":["../../../src/panels/usage/section.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAElD,MAAM,UAAU,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAA0D;IACxG,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACzC,MAAC,IAAI,IAAC,IAAI,EAAC,cAAc,aACvB,KAAC,IAAI,IAAC,IAAI,kBAAE,KAAK,GAAQ,EACxB,KAAK,IAAI,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,kBAAI,KAAK,IAAQ,IAC9C,EACN,QAAQ,IACL,CACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAmB;IAC3C,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IACvK,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;IAClF,IAAI,CAAC,MAAM,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEjD,MAAM,UAAU,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,+BAA+B,CAAC;IAEhF,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,UAAU,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
|
+
import { BarList, Box, dayKey, Heatmap, parseDay, StatGrid, Text, useDayCursor, useInput, useTheme, useWindowSize } from '@jinion/tui';
|
|
4
|
+
import { useAtomValue } from 'jotai';
|
|
5
|
+
import { compact, grouped, plural, shortDate, span } from '@jinion/core/lib/format';
|
|
6
|
+
import { RANGES, totalOf, usageStats } from '@jinion/core/usage/stats';
|
|
7
|
+
import { agentAtom } from '../../state/session.js';
|
|
8
|
+
import { tokenLine } from './section.js';
|
|
9
|
+
const SHARE_BAR = 16;
|
|
10
|
+
const STATS_ROWS = 30;
|
|
11
|
+
export function StatsView({ history, progress, error, available }) {
|
|
12
|
+
const backend = useAtomValue(agentAtom);
|
|
13
|
+
const theme = useTheme();
|
|
14
|
+
const { rows } = useWindowSize();
|
|
15
|
+
const [range, setRange] = useState('all');
|
|
16
|
+
const today = new Date();
|
|
17
|
+
const [day] = useDayCursor(today, { earliest: history?.days[0]?.date });
|
|
18
|
+
const stats = useMemo(() => history && usageStats(history, range), [history, range]);
|
|
19
|
+
const values = useMemo(() => Object.fromEntries((history?.days ?? []).map((item) => [item.date, item.messages])), [history]);
|
|
20
|
+
useInput((input) => {
|
|
21
|
+
if (input === 'r')
|
|
22
|
+
setRange((current) => RANGES[(RANGES.findIndex((candidate) => candidate.range === current) + 1) % RANGES.length].range);
|
|
23
|
+
});
|
|
24
|
+
if (!available)
|
|
25
|
+
return _jsxs(Text, { color: theme.muted, children: [backend.name, " keeps no history of its use."] });
|
|
26
|
+
if (error)
|
|
27
|
+
return _jsxs(Text, { color: theme.error, children: ["Couldn't read the history: ", error] });
|
|
28
|
+
if (!history || !stats) {
|
|
29
|
+
const [done = 0, total = 0] = progress ?? [];
|
|
30
|
+
return (_jsxs(Text, { color: theme.muted, children: ["Reading ", backend.name, "'s conversations on this machine\u2026", total > 0 && ` ${grouped(done)} of ${grouped(total)}`] }));
|
|
31
|
+
}
|
|
32
|
+
const picked = history.days.find((item) => item.date === day);
|
|
33
|
+
const models = stats.models.slice(0, Math.max(1, Math.floor((rows - STATS_ROWS) / 2)));
|
|
34
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { children: RANGES.map((option, index) => (_jsxs(Text, { children: [index > 0 && _jsx(Text, { color: theme.muted, children: " \u00B7 " }), option.range === range ? (_jsx(Text, { color: theme.accent, bold: true, children: option.label })) : (_jsx(Text, { color: theme.muted, children: option.label }))] }, option.range))) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Heatmap, { values: values, end: today, selected: day, legend: true }), _jsxs(Text, { children: [shortDate(parseDay(day)), day === dayKey(today) && _jsx(Text, { color: theme.muted, children: " (today)" }), _jsxs(Text, { color: theme.muted, children: [' · ', picked && picked.messages > 0
|
|
35
|
+
? `${plural(picked.messages, 'message')} · ${plural(picked.sessions, 'session')} · ${compact(Object.values(picked.models).reduce((sum, tokens) => sum + totalOf(tokens), 0))} tokens`
|
|
36
|
+
: 'nothing'] })] })] }), stats.activeDays === 0 ? (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.muted, children: "Nothing in this range yet." }) })) : (_jsxs(_Fragment, { children: [_jsx(Box, { marginTop: 1, children: _jsx(StatGrid, { stats: [
|
|
37
|
+
{ label: 'Favorite model', value: _jsx(Text, { color: theme.accent, children: stats.models[0]?.name ?? '-' }) },
|
|
38
|
+
{ label: 'Tokens', value: _jsx(Text, { color: theme.accent, children: compact(stats.tokens.total) }) },
|
|
39
|
+
{ label: 'Sessions', value: grouped(stats.sessions) },
|
|
40
|
+
{ label: 'Longest session', value: stats.longestSession ? span(stats.longestSession.ms) : '-' },
|
|
41
|
+
{ label: 'Active days', value: grouped(stats.activeDays), detail: `of ${grouped(stats.spanDays)}` },
|
|
42
|
+
{ label: 'Longest streak', value: plural(stats.longestStreak, 'day') },
|
|
43
|
+
{ label: 'Most active day', value: stats.mostActive ? shortDate(parseDay(stats.mostActive.date)) : '-' },
|
|
44
|
+
{ label: 'Current streak', value: plural(stats.currentStreak, 'day') },
|
|
45
|
+
] }) }), _jsx(Text, { color: theme.muted, children: tokenLine(stats.tokens) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(BarList, { width: SHARE_BAR, bars: models.map((model) => ({
|
|
46
|
+
label: model.name,
|
|
47
|
+
value: model.share,
|
|
48
|
+
text: (_jsxs(Text, { children: [`${(model.share * 100).toFixed(1)}%`.padStart(6), _jsxs(Text, { color: theme.muted, children: [" ", compact(model.total)] })] })),
|
|
49
|
+
detail: tokenLine(model.tokens),
|
|
50
|
+
})) }), stats.models.length > models.length && _jsxs(Text, { color: theme.muted, children: ["\u2026 ", plural(stats.models.length - models.length, 'more model')] })] })] }))] }));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=stats-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats-view.js","sourceRoot":"","sources":["../../../src/panels/usage/stats-view.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { Panel, Tabs, useInput, usePanel, useTabs } from '@jinion/tui';
|
|
4
|
+
import { errorMessage } from '@jinion/core/lib/errors';
|
|
5
|
+
import { useAtomValue } from 'jotai';
|
|
6
|
+
import { useApi } from '../../app/api.js';
|
|
7
|
+
import { agentAtom } from '../../state/session.js';
|
|
8
|
+
import { StatsView } from './stats-view.js';
|
|
9
|
+
import { UsageView } from './usage-view.js';
|
|
10
|
+
const TABS = ['Usage', 'Stats'];
|
|
11
|
+
const HINTS = {
|
|
12
|
+
usage: [
|
|
13
|
+
['Tab', 'stats'],
|
|
14
|
+
['d/w', 'last day or week'],
|
|
15
|
+
['Esc', 'close'],
|
|
16
|
+
],
|
|
17
|
+
stats: [
|
|
18
|
+
['Tab', 'usage'],
|
|
19
|
+
['Arrows', 'pick a day'],
|
|
20
|
+
['r', 'range'],
|
|
21
|
+
['Esc', 'close'],
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
export function UsagePanel({ tab = 'usage' }) {
|
|
25
|
+
const agent = useAtomValue(agentAtom);
|
|
26
|
+
const { close } = usePanel();
|
|
27
|
+
const [active] = useTabs(TABS.length, { initial: tab === 'stats' ? 1 : 0, arrows: false });
|
|
28
|
+
const loaded = useUsage(agent.features);
|
|
29
|
+
useInput((_, key) => {
|
|
30
|
+
if (key.escape)
|
|
31
|
+
close();
|
|
32
|
+
});
|
|
33
|
+
return (_jsx(Panel, { title: "Usage", subtitle: agent.name, header: _jsx(Tabs, { tabs: [...TABS], active: active }), grow: true, hints: HINTS[active === 0 ? 'usage' : 'stats'], children: active === 0 ? (_jsx(UsageView, { usage: loaded.usage, error: loaded.usageError, available: agent.features.usage })) : (_jsx(StatsView, { history: loaded.history, progress: loaded.progress, error: loaded.historyError, available: agent.features.history })) }));
|
|
34
|
+
}
|
|
35
|
+
/** Both tabs load at once, so switching shows what is already there. */
|
|
36
|
+
function useUsage(features) {
|
|
37
|
+
const api = useApi();
|
|
38
|
+
const [usage, setUsage] = useState();
|
|
39
|
+
const [usageError, setUsageError] = useState();
|
|
40
|
+
const [history, setHistory] = useState();
|
|
41
|
+
const [progress, setProgress] = useState();
|
|
42
|
+
const [historyError, setHistoryError] = useState();
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
let open = true;
|
|
45
|
+
const failed = (set) => (error) => open && set(errorMessage(error));
|
|
46
|
+
// The limits come quickly; what adds to them takes a look through the week's conversations.
|
|
47
|
+
if (features.usage) {
|
|
48
|
+
api
|
|
49
|
+
.request('usage/limits', { drivers: false })
|
|
50
|
+
.then((quick) => {
|
|
51
|
+
if (!open)
|
|
52
|
+
return;
|
|
53
|
+
setUsage(quick);
|
|
54
|
+
return api.request('usage/limits', { drivers: true }).then((full) => open && setUsage(full));
|
|
55
|
+
})
|
|
56
|
+
.catch(failed(setUsageError));
|
|
57
|
+
}
|
|
58
|
+
const stopProgress = api.client.on('usage/history-progress', ({ done, total }) => open && setProgress([done, total]));
|
|
59
|
+
if (features.history)
|
|
60
|
+
api.request('usage/history', {}).then((days) => open && setHistory(days), failed(setHistoryError));
|
|
61
|
+
return () => {
|
|
62
|
+
open = false;
|
|
63
|
+
stopProgress();
|
|
64
|
+
};
|
|
65
|
+
}, []);
|
|
66
|
+
return { usage, usageError, history, progress, historyError };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=usage-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-panel.js","sourceRoot":"","sources":["../../../src/panels/usage/usage-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { BarList, Box, Meter, Text, useInput, useTheme } from '@jinion/tui';
|
|
4
|
+
import { useAtomValue } from 'jotai';
|
|
5
|
+
import { grouped, money, plural, resetTime, span } from '@jinion/core/lib/format';
|
|
6
|
+
import { agentAtom, identityAtom } from '../../state/session.js';
|
|
7
|
+
import { Section, tokenLine } from './section.js';
|
|
8
|
+
const LIMIT_BAR = 28;
|
|
9
|
+
const SHARE_BAR = 16;
|
|
10
|
+
const TRAITS = {
|
|
11
|
+
subagents: ['Subagent-heavy', 'each subagent makes requests of its own'],
|
|
12
|
+
'long-context': ['Long context', 'requests past 150k tokens; /clear between tasks keeps them small'],
|
|
13
|
+
'cache-misses': ['Cache misses', 'requests that missed the prompt cache, e.g. after an hour away'],
|
|
14
|
+
parallel: ['Parallel', 'while four or more sessions ran at once'],
|
|
15
|
+
scheduled: ['Scheduled', 'from scheduled or looping sessions'],
|
|
16
|
+
};
|
|
17
|
+
const SOURCE_KINDS = { skill: 'skill', agent: 'subagent', plugin: 'plugin', mcp: 'MCP' };
|
|
18
|
+
export function UsageView({ usage, error, available }) {
|
|
19
|
+
const backend = useAtomValue(agentAtom);
|
|
20
|
+
const theme = useTheme();
|
|
21
|
+
const plan = useAtomValue(identityAtom)?.plan;
|
|
22
|
+
const [window, setWindow] = useState('day');
|
|
23
|
+
useInput((input) => {
|
|
24
|
+
if (input === 'd')
|
|
25
|
+
setWindow('day');
|
|
26
|
+
if (input === 'w')
|
|
27
|
+
setWindow('week');
|
|
28
|
+
});
|
|
29
|
+
if (!available)
|
|
30
|
+
return _jsxs(Text, { color: theme.muted, children: [backend.name, " doesn't report its usage."] });
|
|
31
|
+
if (error)
|
|
32
|
+
return _jsxs(Text, { color: theme.error, children: ["Couldn't ask ", backend.name, " for its usage: ", error] });
|
|
33
|
+
if (!usage)
|
|
34
|
+
return _jsxs(Text, { color: theme.muted, children: ["Asking ", backend.name, " for its usage\u2026"] });
|
|
35
|
+
const { session, limits, extra, drivers } = usage;
|
|
36
|
+
const labelWidth = Math.max(0, ...limits.map((limit) => limit.label.length)) + 2;
|
|
37
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Section, { title: "Plan limits", aside: plan, children: [limits.length === 0 ? (_jsx(Text, { color: theme.muted, children: "This login has no plan limits, e.g. an API key." })) : (limits.map((limit) => (_jsxs(Text, { children: [limit.label.padEnd(labelWidth), _jsx(Meter, { value: limit.used, width: LIMIT_BAR }), " ", `${Math.round(limit.used * 100)}%`.padStart(4), limit.resetsAt !== undefined && _jsxs(Text, { color: theme.muted, children: [" resets ", resetTime(limit.resetsAt)] })] }, limit.label)))), extra && (_jsxs(Text, { color: theme.muted, children: ["Extra usage ", money(extra.used, extra.currency), extra.limit !== undefined && ` of ${money(extra.limit, extra.currency)}`, " this month"] }))] }), session && (_jsx(Section, { title: "This session", aside: `${money(session.cost)} · ${span(session.apiMs)} waiting on the model · ${span(session.wallMs)} in all · +${grouped(session.linesAdded)} -${grouped(session.linesRemoved)} lines`, children: session.models.length === 0 ? (_jsx(Text, { color: theme.muted, children: "No requests yet." })) : (session.models.map((model, _, models) => (_jsxs(Text, { wrap: "truncate-end", children: [model.name.padEnd(Math.max(...models.map((other) => other.name.length)) + 2), _jsx(Text, { color: theme.muted, children: tokenLine(model).padEnd(Math.max(...models.map((other) => tokenLine(other).length)) + 2) }), money(model.cost)] }, model.name)))) })), _jsx(Section, { title: `What adds to your limits · last ${window === 'day' ? '24 hours' : '7 days'}`, children: _jsx(Drivers, { drivers: drivers?.[window], loading: !drivers }) })] }));
|
|
38
|
+
}
|
|
39
|
+
function Drivers({ drivers, loading }) {
|
|
40
|
+
const theme = useTheme();
|
|
41
|
+
if (loading)
|
|
42
|
+
return _jsx(Text, { color: theme.muted, children: "Looking through this week's conversations on this machine\u2026" });
|
|
43
|
+
if (!drivers || drivers.requests === 0)
|
|
44
|
+
return _jsx(Text, { color: theme.muted, children: "Nothing in this time on this machine." });
|
|
45
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Text, { color: theme.muted, children: [plural(drivers.requests, 'request'), " in ", plural(drivers.sessions, 'session'), " on this machine, roughly. The traits overlap, so they don't add up."] }), _jsx(Box, { marginTop: 1, children: _jsx(BarList, { width: SHARE_BAR, bars: drivers.traits.map(({ trait, share }) => ({
|
|
46
|
+
label: TRAITS[trait][0],
|
|
47
|
+
value: share,
|
|
48
|
+
text: (_jsxs(Text, { children: [`${Math.round(share * 100)}%`.padStart(4), _jsxs(Text, { color: theme.muted, children: [" ", TRAITS[trait][1]] })] })),
|
|
49
|
+
})) }) }), drivers.sources.length > 0 && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { wrap: "truncate-end", children: [_jsx(Text, { color: theme.muted, children: "Most used: " }), drivers.sources.slice(0, 5).map((source, index) => (_jsxs(Text, { children: [index > 0 && _jsx(Text, { color: theme.muted, children: " \u00B7 " }), source.name, _jsxs(Text, { color: theme.muted, children: [' ', SOURCE_KINDS[source.kind], " ", Math.round(source.share * 100), "%"] })] }, `${source.kind}:${source.name}`)))] }) }))] }));
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=usage-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-view.js","sourceRoot":"","sources":["../../../src/panels/usage/usage-view.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB,MAAM,MAAM,GAAkF;IAC5F,SAAS,EAAE,CAAC,gBAAgB,EAAE,yCAAyC,CAAC;IACxE,cAAc,EAAE,CAAC,cAAc,EAAE,kEAAkE,CAAC;IACpG,cAAc,EAAE,CAAC,cAAc,EAAE,gEAAgE,CAAC;IAClG,QAAQ,EAAE,CAAC,UAAU,EAAE,yCAAyC,CAAC;IACjE,SAAS,EAAE,CAAC,WAAW,EAAE,oCAAoC,CAAC;CAC/D,CAAC;AAEF,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAW,CAAC;AAElG,MAAM,UAAU,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAA8D;IAC/G,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,YAAY,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC;IAE9C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAiB,KAAK,CAAC,CAAC;IAE5D,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE;QACjB,IAAI,KAAK,KAAK,GAAG;YAAE,SAAS,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,KAAK,KAAK,GAAG;YAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS;QAAE,OAAO,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,aAAG,OAAO,CAAC,IAAI,kCAAkC,CAAC;IACjG,IAAI,KAAK;QAAE,OAAO,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,8BAAgB,OAAO,CAAC,IAAI,sBAAkB,KAAK,IAAQ,CAAC;IACtG,IAAI,CAAC,KAAK;QAAE,OAAO,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,wBAAU,OAAO,CAAC,IAAI,4BAAuB,CAAC;IAEzF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IAEjF,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,MAAC,OAAO,IAAC,KAAK,EAAC,aAAa,EAAC,KAAK,EAAE,IAAI,aACrC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CACrB,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,gEAAwD,CACjF,CAAC,CAAC,CAAC,CACF,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CACpB,MAAC,IAAI,eACF,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,EAC/B,KAAC,KAAK,IAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,GAAI,OAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAC7F,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,yBAAW,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAQ,KAH5F,KAAK,CAAC,KAAK,CAIf,CACR,CAAC,CACH,EACA,KAAK,IAAI,CACR,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,6BACT,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,EAC7C,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,mBACpE,CACR,IACO,EAET,OAAO,IAAI,CACV,KAAC,OAAO,IACN,KAAK,EAAC,cAAc,EACpB,KAAK,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,2BAA2B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,cAAc,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,QAAQ,YAEvL,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAC7B,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,iCAAyB,CAClD,CAAC,CAAC,CAAC,CACF,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,CACvC,MAAC,IAAI,IAAkB,IAAI,EAAC,cAAc,aACvC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAC7E,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,YAAG,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAQ,EAC1H,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAHT,KAAK,CAAC,IAAI,CAId,CACR,CAAC,CACH,GACO,CACX,EAED,KAAC,OAAO,IAAC,KAAK,EAAE,mCAAmC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,YAC3F,KAAC,OAAO,IAAC,OAAO,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,OAAO,GAAI,GAClD,IACN,CACP,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,EAAgD;IACjF,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IAEzB,IAAI,OAAO;QAAE,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,gFAAmE,CAAC;IAChH,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,sDAA8C,CAAC;IAEtH,OAAO,CACL,8BACE,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,aACrB,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,UAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,4EAExE,EACP,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,OAAO,IACN,KAAK,EAAE,SAAS,EAChB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;wBAC9C,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;wBACvB,KAAK,EAAE,KAAK;wBACZ,IAAI,EAAE,CACJ,MAAC,IAAI,eACF,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAC1C,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,kBAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAQ,IAC/C,CACR;qBACF,CAAC,CAAC,GACH,GACE,EACL,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAC7B,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,MAAC,IAAI,IAAC,IAAI,EAAC,cAAc,aACvB,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,4BAAoB,EAC3C,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAClD,MAAC,IAAI,eACF,KAAK,GAAG,CAAC,IAAI,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,yBAAY,EACjD,MAAM,CAAC,IAAI,EACZ,MAAC,IAAI,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,aACrB,GAAG,EACH,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,OAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,GAAG,GAAG,CAAC,SACtD,KANE,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAOnC,CACR,CAAC,IACG,GACH,CACP,IACA,CACJ,CAAC;AACJ,CAAC"}
|