jaitus 0.3.19 → 0.3.21
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 +1 -1
- package/README.md +66 -30
- package/package.json +1 -1
- package/src/agent/loop.js +10 -11
- package/src/api.js +3 -3
- package/src/brand.js +233 -232
- package/src/commands/doctor.js +11 -10
- package/src/commands/login.js +3 -3
- package/src/commands/logout.js +1 -1
- package/src/commands/update.js +11 -2
- package/src/errors.js +10 -9
- package/src/index.js +44 -44
- package/src/logo-data.js +2 -2
- package/src/planView.js +89 -29
- package/src/skills.js +1 -1
- package/src/tui/entries.js +2 -2
- package/src/tui/theme.js +21 -21
- package/src/tui/wordmark.js +1 -1
- package/src/tui-ink.js +2941 -2921
- package/src/tui.js +2556 -2560
- package/src/ui.js +11 -11
package/src/errors.js
CHANGED
|
@@ -10,30 +10,31 @@
|
|
|
10
10
|
const CATALOG = {
|
|
11
11
|
auth_required: { title: 'Not signed in', hint: 'Type /login to sign in (or run `jaitus login`).' },
|
|
12
12
|
session_expired: { title: 'Signed out', hint: 'Type /login to sign in again (or run `jaitus login`).' },
|
|
13
|
-
account_suspended: { title: 'Account suspended', hint: 'Contact support if you think this is a mistake.' },
|
|
13
|
+
account_suspended: { title: 'Account suspended', hint: 'Contact support@jaitus.com if you think this is a mistake.' },
|
|
14
14
|
email_unverified: { title: 'Email not verified', hint: 'Open the verification link in your inbox, then retry.' },
|
|
15
|
-
free_limit_reached: { title: 'Free
|
|
16
|
-
free_machine_limit: { title: 'No free prompts on this account', hint: 'Subscribe
|
|
15
|
+
free_limit_reached: { title: 'Free allowance used up', hint: 'Subscribe at jaitus.com/billing, then retry this turn. Pay by UPI, card, net banking or wallet; the plan starts as soon as the payment goes through.' },
|
|
16
|
+
free_machine_limit: { title: 'No free prompts on this account', hint: 'Subscribe at jaitus.com/billing to keep using Jaitus on this account.' },
|
|
17
17
|
free_needs_check: { title: 'Unlock your free prompts', hint: 'A one-time ₹1 UPI check at jaitus.com/billing (refunded). Or subscribe.' },
|
|
18
18
|
free_needs_cli: { title: 'Update Jaitus for free prompts', hint: 'Run npm i -g jaitus, then try again.' },
|
|
19
|
-
free_request_too_large: { title: 'Too large for the free plan', hint: 'Run /compact or start a new session, or subscribe.' },
|
|
20
|
-
plan_limit_reached: { title: 'Monthly usage used up', hint: '
|
|
19
|
+
free_request_too_large: { title: 'Too large for the free plan', hint: 'Run /compact or start a new session, or subscribe at jaitus.com/billing.' },
|
|
20
|
+
plan_limit_reached: { title: 'Monthly usage used up', hint: 'To keep going now, switch plans at jaitus.com/billing — what is left of this plan carries over. Buying another 30 days of the same plan adds days but does not refill this month. /usage shows where you are.' },
|
|
21
21
|
rate_limited: { title: 'Slow down', hint: 'Wait a moment, then retry.' },
|
|
22
22
|
context_too_long: { title: 'Conversation too long', hint: 'Run /compact, or start a new session.' },
|
|
23
23
|
request_too_large: { title: 'Request too large', hint: 'Usually images: remove some, or run /compact to drop old ones. Images over 3.5 MB are shrunk automatically.' },
|
|
24
24
|
daily_limit_reached: { title: 'Usage limit reached', hint: 'It refills automatically. /usage shows where you are.' },
|
|
25
|
-
|
|
25
|
+
plan_expired: { title: 'Your plan has ended', hint: 'Plans last 30 days and do not renew by themselves. Renew at jaitus.com/billing, then retry this turn.' },
|
|
26
|
+
window_limit_reached: { title: 'Usage limit reached', hint: 'It resets by itself — /usage shows your 5-hour window, week and month, and when each resets.' },
|
|
26
27
|
token_expired: { title: 'Signed out', hint: 'Type /login to sign in again (or run `jaitus login`).' },
|
|
27
28
|
refresh_race: { title: 'Sign-in was being renewed', hint: 'Try again.' },
|
|
28
29
|
content_blocked: { title: 'Request refused', hint: 'Rephrase the request and try again.' },
|
|
29
|
-
bad_request: { title: 'Request not accepted', hint: 'Try again; if it repeats, run /debug and
|
|
30
|
-
model_unavailable: { title: 'Model unavailable', hint: 'Run
|
|
30
|
+
bad_request: { title: 'Request not accepted', hint: 'Try again; if it repeats, run /debug and send the output to support@jaitus.com.' },
|
|
31
|
+
model_unavailable: { title: 'Model unavailable', hint: 'Run `jaitus config model --unset` so Jaitus picks the model automatically.' },
|
|
31
32
|
busy: { title: 'Jaitus is busy', hint: 'Try again in a minute.' },
|
|
32
33
|
unavailable: { title: 'Jaitus is unavailable', hint: 'Try again shortly. `jaitus doctor` checks your side.' },
|
|
33
34
|
maintenance: { title: 'Down for maintenance', hint: 'Try again shortly.' },
|
|
34
35
|
timeout: { title: 'Timed out', hint: 'Try again.' },
|
|
35
36
|
interrupted: { title: 'Response interrupted', hint: 'Try again.' },
|
|
36
|
-
internal: { title: 'Something went wrong', hint: 'Try again; if it keeps happening,
|
|
37
|
+
internal: { title: 'Something went wrong', hint: 'Try again; if it keeps happening, email support@jaitus.com with the request id.' },
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
const GENERIC = 'Something went wrong in Jaitus.';
|
package/src/index.js
CHANGED
|
@@ -67,13 +67,13 @@ const OPTIONS = [
|
|
|
67
67
|
['--print, -p', 'run one prompt non-interactively and exit'],
|
|
68
68
|
['--continue, -c', 'continue the most recent session in this directory'],
|
|
69
69
|
['--resume, -r <id>', 'resume a session by id'],
|
|
70
|
-
['--output-format <format>', '
|
|
70
|
+
['--output-format <format>', 'text, json or stream-json (with --print)'],
|
|
71
71
|
['--max-turns <n>', 'limit agent turns in non-interactive mode'],
|
|
72
72
|
['--permission-mode <mode>', 'default, acceptEdits, plan or bypassPermissions'],
|
|
73
73
|
['--dangerously-skip-permissions', 'alias for bypassPermissions; trusted workspaces only'],
|
|
74
74
|
['--system-prompt <text>', 'replace the model system prompt in print mode'],
|
|
75
75
|
['--append-system-prompt <text>', 'add instructions to the system prompt'],
|
|
76
|
-
['--model <id>', '
|
|
76
|
+
['--model <id>', 'model id for this run (leave it out: Jaitus picks the model for each request)'],
|
|
77
77
|
['--cwd <dir>', 'work in another directory'],
|
|
78
78
|
['--yes, -y', 'do not ask before writing files or running commands'],
|
|
79
79
|
['--json', 'machine-readable output, where a command reports something'],
|
|
@@ -237,8 +237,8 @@ async function resolveModel(client, preferred) {
|
|
|
237
237
|
// one the gateway does not list produces a confusing rejection instead of this.
|
|
238
238
|
if (!available.length) {
|
|
239
239
|
throw new NoModel(
|
|
240
|
-
'
|
|
241
|
-
+ 'Run `jaitus doctor` to see where it stopped
|
|
240
|
+
'Jaitus did not send its model list, so there is nothing to run against. '
|
|
241
|
+
+ 'Run `jaitus doctor` to see where it stopped.'
|
|
242
242
|
);
|
|
243
243
|
}
|
|
244
244
|
return available[0];
|
|
@@ -322,7 +322,6 @@ function reportAgentError(e, context = {}) {
|
|
|
322
322
|
if (isJaitusError(error)) {
|
|
323
323
|
fail(error.message);
|
|
324
324
|
if (error.hint) info(error.hint);
|
|
325
|
-
if (error.code === 'free_limit_reached' || error.code === 'free_request_too_large') info('Subscribe at ' + endpoints().siteUrl + '/billing');
|
|
326
325
|
if (error.requestId) info(c.dim(`request id ${error.requestId}`));
|
|
327
326
|
} else if (error instanceof NotSignedIn) {
|
|
328
327
|
fail(error.message);
|
|
@@ -361,10 +360,9 @@ async function loadContextBudget(client) {
|
|
|
361
360
|
// Compact at this fraction of the budget. Low enough that the summarisation request
|
|
362
361
|
// itself still fits comfortably, high enough that a normal session never sees it.
|
|
363
362
|
const AUTO_COMPACT_AT = 0.78;
|
|
364
|
-
// The budget is what the
|
|
365
|
-
//
|
|
366
|
-
//
|
|
367
|
-
// would silently override whatever the admin set.
|
|
363
|
+
// The budget is what the server advertises. That number is the ONE control for how big
|
|
364
|
+
// a session gets before it is summarised: a second ceiling here would silently override
|
|
365
|
+
// whatever the server set.
|
|
368
366
|
const compactThreshold = () => CONTEXT_BUDGET * AUTO_COMPACT_AT;
|
|
369
367
|
|
|
370
368
|
// An expanded @mention is capped: pulling a 4 MB lockfile into the prompt because
|
|
@@ -570,7 +568,7 @@ async function oneShot(task, { flags }) {
|
|
|
570
568
|
|
|
571
569
|
const SLASH = {
|
|
572
570
|
'/help': { summary: 'these commands' },
|
|
573
|
-
'/model [id]': { summary: '
|
|
571
|
+
'/model [id]': { summary: 'the model setting (jaitus-auto: Jaitus picks the model for each request)' },
|
|
574
572
|
'/models': { summary: 'model ids Jaitus accepts', hidden: true }, // duplicate of /model, which lists them and lets you pick
|
|
575
573
|
'/status': { summary: 'model, mode, account, directory, context usage' },
|
|
576
574
|
'/cost': { summary: 'tokens used so far this session' },
|
|
@@ -578,7 +576,7 @@ const SLASH = {
|
|
|
578
576
|
'/cwd': { summary: 'which directory the agent is working in', hidden: true }, // already in the header and in /status
|
|
579
577
|
'/clear': { summary: 'start the conversation over' },
|
|
580
578
|
'/undo': { summary: 'drop the last exchange' },
|
|
581
|
-
'/compact [focus]': { summary: '
|
|
579
|
+
'/compact [focus]': { summary: 'summarise the conversation to free context' },
|
|
582
580
|
'/export [file]': { summary: 'write the conversation to a file (txt/md/json)' },
|
|
583
581
|
'/copy': { summary: 'copy the last response to the clipboard' },
|
|
584
582
|
'/diff': { summary: 'uncommitted changes, staged or not, and new files' },
|
|
@@ -594,7 +592,7 @@ const SLASH = {
|
|
|
594
592
|
'/hooks': { summary: 'show configured lifecycle hooks' },
|
|
595
593
|
'/tui [fullscreen|default]': { summary: 'switch renderer, relaunching with this conversation intact' },
|
|
596
594
|
'/fork': { summary: 'copy this conversation into a brand-new session id', hidden: true }, // duplicate of /branch
|
|
597
|
-
'/theme [name]': { summary: 'show or set the
|
|
595
|
+
'/theme [name]': { summary: 'show or set the colour theme (dark, light, daltonized, ocean, plain, auto)' },
|
|
598
596
|
'/scroll-speed [n]': { summary: 'show or set mouse-wheel scroll speed (0.25-10)', hidden: true }, // belongs in /config
|
|
599
597
|
'/vim': { summary: 'toggle Vim modal editing for the prompt' },
|
|
600
598
|
'/attach <id>': { summary: 'watch a background job log live (Esc stops watching)' },
|
|
@@ -617,14 +615,14 @@ const SLASH = {
|
|
|
617
615
|
'/plan [task]': { summary: 'read-only plan mode, optionally for one task' },
|
|
618
616
|
'/branch [name]': { summary: 'branch the conversation, return with /resume' },
|
|
619
617
|
'/rewind [turn]': { summary: 'restore conversation and files to an earlier turn' },
|
|
620
|
-
'/feedback [text]': { summary: '
|
|
618
|
+
'/feedback [text]': { summary: 'save a note about a problem, with session details, on this computer' },
|
|
621
619
|
'/version': { summary: 'print the running version', hidden: true }, // already in /status
|
|
622
620
|
'/animations [on|off]': { summary: 'motion: shimmer, sweeps, stagger (or stillness)', hidden: true }, // belongs in /config
|
|
623
621
|
'/login': { summary: 'sign in as a different account' },
|
|
624
622
|
'/logout': { summary: 'sign this device out and leave' },
|
|
625
623
|
'/doctor': { summary: 'diagnose setup problems' },
|
|
626
624
|
'/whoami': { summary: 'who you are signed in as' },
|
|
627
|
-
'/usage': { summary:
|
|
625
|
+
'/usage': { summary: "your plan's 5-hour window, weekly and monthly usage (or free prompts left)" },
|
|
628
626
|
'/init': { summary: 'create JAITUS.md and .jaitusignore here' },
|
|
629
627
|
'/mcp [list|add|remove]': { summary: 'list or configure MCP tool servers' },
|
|
630
628
|
'/config [key] [value]': { summary: 'show or change CLI settings' },
|
|
@@ -1080,7 +1078,7 @@ async function session({ flags }) {
|
|
|
1080
1078
|
messages.push({ role: 'assistant', content: `[No reply — this request failed: ${what}]` });
|
|
1081
1079
|
}
|
|
1082
1080
|
} else {
|
|
1083
|
-
ledger.note('turn-failed', `A request to
|
|
1081
|
+
ledger.note('turn-failed', `A request to Jaitus failed${e.status ? ` with HTTP ${e.status}` : ''} partway through the task: ${e.message}. The steps before it are kept; it did not finish.`);
|
|
1084
1082
|
}
|
|
1085
1083
|
} finally {
|
|
1086
1084
|
// Whatever ended the run, the history leaves here well-formed: every tool call
|
|
@@ -1530,7 +1528,7 @@ async function session({ flags }) {
|
|
|
1530
1528
|
// place that knows how to reach a clipboard on each platform.
|
|
1531
1529
|
tui.onCopy?.((text) => copyToClipboard(text));
|
|
1532
1530
|
} else if (!unicode() && !process.env.JAITUS_NO_BANNER) {
|
|
1533
|
-
// Plain-console open,
|
|
1531
|
+
// Plain-console open, a one-block session header: lowercase wordmark,
|
|
1534
1532
|
// model, approval posture, directory, account — one compact block,
|
|
1535
1533
|
// instant, nothing repeated.
|
|
1536
1534
|
const { renderClassicOpen } = await import('./brand.js');
|
|
@@ -1568,7 +1566,7 @@ async function session({ flags }) {
|
|
|
1568
1566
|
// so colors and the app view are off and plain text is the honest UI.
|
|
1569
1567
|
// Said once ever (flagged in settings), then never again.
|
|
1570
1568
|
if (!device.vt && process.stdout.isTTY && !savedTui && !loadSettings().legacyNoted) {
|
|
1571
|
-
out(' Plain-text console: for
|
|
1569
|
+
out(' Plain-text console: for colours, mouse and fullscreen, use Windows Terminal.');
|
|
1572
1570
|
try { saveSettings({ ...loadSettings(), legacyNoted: true }); } catch { /* notice is courtesy, not contract */ }
|
|
1573
1571
|
}
|
|
1574
1572
|
const projectNotes = loadContext(flags.cwd);
|
|
@@ -1839,7 +1837,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
1839
1837
|
[` ${c.dim('estimated tokens')}`, tokens.toLocaleString()],
|
|
1840
1838
|
...(loadContext(ctx.flags.cwd) ? [[` ${c.dim('project notes')}`, `${CONTEXT_FILE} (loaded)`]] : []),
|
|
1841
1839
|
]);
|
|
1842
|
-
info(`${c.dim('Run')} ${c.bold('/compact')} ${c.dim('to
|
|
1840
|
+
info(`${c.dim('Run')} ${c.bold('/compact')} ${c.dim('to summarise and free context when this grows.')}`);
|
|
1843
1841
|
return null;
|
|
1844
1842
|
}
|
|
1845
1843
|
|
|
@@ -1849,8 +1847,8 @@ async function slashCommand(verb, args, ctx) {
|
|
|
1849
1847
|
// report through the app status row instead.
|
|
1850
1848
|
const spin = ctx.tui
|
|
1851
1849
|
? { stop: () => ctx.tui.clearStatus(), update: () => {} }
|
|
1852
|
-
: (await import('./ui.js')).spinner('
|
|
1853
|
-
if (ctx.tui) ctx.tui.setStatus(`${c.brand(glyph('◆', '*'))} ${c.brand(glyph('
|
|
1850
|
+
: (await import('./ui.js')).spinner('Summarising…');
|
|
1851
|
+
if (ctx.tui) ctx.tui.setStatus(`${c.brand(glyph('◆', '*'))} ${c.brand(glyph('Summarising…', 'Summarising...'))}`);
|
|
1854
1852
|
try {
|
|
1855
1853
|
const before = estimateTokens(ctx.messages);
|
|
1856
1854
|
// Images are the usual reason a request is too large in bytes; the summary keeps
|
|
@@ -1858,7 +1856,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
1858
1856
|
dropOldImages(ctx.messages);
|
|
1859
1857
|
const r = await compactInPlace(ctx.client, ctx.model, ctx.messages, {
|
|
1860
1858
|
focus: args.join(' '), contextTokens: CONTEXT_BUDGET, keepTail: false,
|
|
1861
|
-
onProgress: (i, n) => ctx.tui?.setStatus?.(`${c.brand(glyph('◆', '*'))}
|
|
1859
|
+
onProgress: (i, n) => ctx.tui?.setStatus?.(`${c.brand(glyph('◆', '*'))} Summarising a long session — part ${i} of ${n}`),
|
|
1862
1860
|
});
|
|
1863
1861
|
// Saved now: a crash before the next turn used to bring the whole history back.
|
|
1864
1862
|
if (ctx.sessionState) { ctx.sessionState.messages = ctx.messages; ctx.sessionState.lastContext = 0; saveSession(ctx.sessionState); }
|
|
@@ -1930,7 +1928,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
1930
1928
|
|
|
1931
1929
|
case '/image': {
|
|
1932
1930
|
const [p] = args;
|
|
1933
|
-
if (!p) { warn('Give an image path: /image screenshot.png (png, jpg, gif
|
|
1931
|
+
if (!p) { warn('Give an image path: /image screenshot.png (png, jpg, gif or webp; anything over 3.5 MB is shrunk automatically).'); return null; }
|
|
1934
1932
|
// A path with spaces arrives split into args; quotes around it are the user's.
|
|
1935
1933
|
const joined = args.join(' ').replace(/^["']|["']$/g, '');
|
|
1936
1934
|
const abs = path.isAbsolute(joined) ? joined : path.join(ctx.flags.cwd, joined);
|
|
@@ -2228,7 +2226,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
2228
2226
|
if (!ctx.tui) { info(`Theme: ${c.bold(loadS2().theme || 'auto')} (${names.join(', ')})`); return null; }
|
|
2229
2227
|
const picked = await pickOption(ctx.tui, 'Theme', 'Which theme should the CLI wear?', names.map((n) => ({
|
|
2230
2228
|
value: n,
|
|
2231
|
-
label: `${n === (loadS2().theme || 'auto') ? '●' : '○'} ${n}${n === 'auto' ? ' (follows the terminal)' : ''}${n === 'daltonized' ? ' (
|
|
2229
|
+
label: `${n === (loadS2().theme || 'auto') ? '●' : '○'} ${n}${n === 'auto' ? ' (follows the terminal)' : ''}${n === 'daltonized' ? ' (colourblind-safe)' : ''}`,
|
|
2232
2230
|
})));
|
|
2233
2231
|
if (!picked) return null;
|
|
2234
2232
|
applyTheme(picked);
|
|
@@ -2536,7 +2534,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
2536
2534
|
const line = `[${new Date().toISOString()}] session=${ctx.sessionState.id} model=${ctx.model} cwd=${ctx.flags.cwd} turns=${spent.turns}\n ${text.replace(/\n/g, '\n ')}\n`;
|
|
2537
2535
|
fs.appendFileSync(path.join(HOME, 'feedback.log'), line, 'utf8');
|
|
2538
2536
|
// Saved here only — it is not sent anywhere, and saying otherwise was untrue.
|
|
2539
|
-
ok(`Saved to ${c.bold('~/.jaitus/feedback.log')} on this computer (it is not sent anywhere). ${c.dim('
|
|
2537
|
+
ok(`Saved to ${c.bold('~/.jaitus/feedback.log')} on this computer (it is not sent anywhere). ${c.dim('Email it to support@jaitus.com if you want us to see it; /export writes the conversation to a file.')}`);
|
|
2540
2538
|
} catch (e) {
|
|
2541
2539
|
fail(`Could not save feedback: ${e.message}`);
|
|
2542
2540
|
}
|
|
@@ -2568,7 +2566,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
2568
2566
|
t.notice('Opening your browser to sign in. If it does not open, paste this link:', 'info');
|
|
2569
2567
|
t.notice(url, 'dim');
|
|
2570
2568
|
},
|
|
2571
|
-
onStatus: (s) => t.setStatus(s === 'waiting' ? 'Waiting for you to approve in the browser… (
|
|
2569
|
+
onStatus: (s) => t.setStatus(s === 'waiting' ? 'Waiting for you to approve in the browser… (press Cancel on that page to stop; it gives up after 5 minutes)' : 'Finishing sign-in…'),
|
|
2572
2570
|
});
|
|
2573
2571
|
t.clearStatus?.();
|
|
2574
2572
|
if (result.ok) t.notice(`Signed in as ${result.user?.email || 'your account'}${result.user?.isPaid ? '' : ' (free plan)'}.`, 'ok');
|
|
@@ -2615,7 +2613,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
2615
2613
|
return null;
|
|
2616
2614
|
|
|
2617
2615
|
case '/banner': {
|
|
2618
|
-
// Session header on demand,
|
|
2616
|
+
// Session header on demand, as one block.
|
|
2619
2617
|
const modeApproval = ctx.permissions.mode === 'plan' ? 'read-only'
|
|
2620
2618
|
: ctx.permissions.mode === 'acceptEdits' ? 'auto-edit'
|
|
2621
2619
|
: ctx.permissions.mode === 'bypassPermissions' ? 'bypass' : 'ask';
|
|
@@ -2660,15 +2658,15 @@ async function slashCommand(verb, args, ctx) {
|
|
|
2660
2658
|
};
|
|
2661
2659
|
if (args[0]) {
|
|
2662
2660
|
if (available.length && !available.includes(args[0])) {
|
|
2663
|
-
warn(`
|
|
2661
|
+
warn(`Jaitus does not accept ${args[0]}. It accepts: ${available.join(', ')}`);
|
|
2664
2662
|
return null;
|
|
2665
2663
|
}
|
|
2666
2664
|
applyModel(args[0]);
|
|
2667
2665
|
return null;
|
|
2668
2666
|
}
|
|
2669
|
-
if (!available.length) { warn('
|
|
2670
|
-
if (!ctx.tui) { info(`Model: ${c.bold(ctx.model)}
|
|
2671
|
-
const picked = await pickOption(ctx.tui, 'Model', '
|
|
2667
|
+
if (!available.length) { warn('Jaitus sent no model list. Run `jaitus doctor`.'); return null; }
|
|
2668
|
+
if (!ctx.tui) { info(`Model: ${c.bold(ctx.model)} — Jaitus picks the model for each request.`); return null; }
|
|
2669
|
+
const picked = await pickOption(ctx.tui, 'Model', 'Jaitus picks the model for each request. Model setting for this session:',
|
|
2672
2670
|
available.slice(0, 20).map((m) => ({ value: m, label: `${m === ctx.model ? '●' : '○'} ${m}` })));
|
|
2673
2671
|
if (!picked) return null;
|
|
2674
2672
|
applyModel(picked);
|
|
@@ -2677,7 +2675,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
2677
2675
|
|
|
2678
2676
|
case '/models': {
|
|
2679
2677
|
const list = await client.models();
|
|
2680
|
-
if (!list.length) { warn('
|
|
2678
|
+
if (!list.length) { warn('Jaitus sent no model list. Run `jaitus doctor`.'); return null; }
|
|
2681
2679
|
list.forEach((m) => out(` ${m === ctx.model ? c.brand('●') : c.grey('○')} ${m}`));
|
|
2682
2680
|
return null;
|
|
2683
2681
|
}
|
|
@@ -2695,7 +2693,7 @@ async function slashCommand(verb, args, ctx) {
|
|
|
2695
2693
|
[' Cached input tokens', (spent.cached || 0).toLocaleString()],
|
|
2696
2694
|
[' Output tokens', spent.output.toLocaleString()],
|
|
2697
2695
|
]);
|
|
2698
|
-
info(`${c.dim('Plan usage is this session as a share of your 5-hour
|
|
2696
|
+
info(`${c.dim('Plan usage is this session as a share of your 5-hour, weekly and monthly limits. See')} ${c.bold('/usage')} ${c.dim('for your plan.')}`);
|
|
2699
2697
|
return null;
|
|
2700
2698
|
|
|
2701
2699
|
case '/cwd':
|
|
@@ -2774,14 +2772,14 @@ const commands = {
|
|
|
2774
2772
|
present(json, withoutCredits(u), () => table([
|
|
2775
2773
|
['Account', u.email || '—'],
|
|
2776
2774
|
...planRows(u),
|
|
2777
|
-
['
|
|
2775
|
+
['Server', endpoints().baseUrl],
|
|
2778
2776
|
]));
|
|
2779
2777
|
return 0;
|
|
2780
2778
|
},
|
|
2781
2779
|
},
|
|
2782
2780
|
|
|
2783
2781
|
usage: {
|
|
2784
|
-
summary:
|
|
2782
|
+
summary: "your plan's 5-hour window, weekly and monthly usage (or free prompts left)",
|
|
2785
2783
|
usage: ['jaitus usage [--json]'],
|
|
2786
2784
|
run: async (argv, { json, tui = null, spent = null } = {}) => {
|
|
2787
2785
|
const client = requireAuth();
|
|
@@ -2797,7 +2795,9 @@ const commands = {
|
|
|
2797
2795
|
{ gap: true },
|
|
2798
2796
|
{ heading: 'Requests' },
|
|
2799
2797
|
{ label: 'Today', value: `${(d.today?.requests ?? 0).toLocaleString()} requests` },
|
|
2800
|
-
|
|
2798
|
+
// The server counts these from the 1st of the calendar month — not the plan's
|
|
2799
|
+
// 30-day month above — so the label names the date rather than saying "month".
|
|
2800
|
+
{ label: `Since ${new Date(new Date().getFullYear(), new Date().getMonth(), 1).toLocaleDateString([], { day: 'numeric', month: 'short' })}`, value: `${(d.month?.requests ?? 0).toLocaleString()} requests · ${fmtTokens(d.month?.tokens ?? 0)} tokens` },
|
|
2801
2801
|
];
|
|
2802
2802
|
if (u?.planStatus) rememberPlan(u.planStatus);
|
|
2803
2803
|
const used = spent ? spendText(spent.credits || 0) : '';
|
|
@@ -2815,12 +2815,12 @@ const commands = {
|
|
|
2815
2815
|
},
|
|
2816
2816
|
|
|
2817
2817
|
models: {
|
|
2818
|
-
summary: 'model ids
|
|
2818
|
+
summary: 'model ids Jaitus accepts (it picks the model for each request)',
|
|
2819
2819
|
usage: ['jaitus models [--json]'],
|
|
2820
2820
|
run: async (argv, { json }) => {
|
|
2821
2821
|
const client = requireAuth();
|
|
2822
2822
|
const list = await client.models();
|
|
2823
|
-
if (!list.length) { warn('
|
|
2823
|
+
if (!list.length) { warn('Jaitus sent no model list. Run `jaitus doctor`.'); return 1; }
|
|
2824
2824
|
const current = loadSettings().model;
|
|
2825
2825
|
present(json, { models: list, default: current || list[0] }, () => {
|
|
2826
2826
|
list.forEach((m) => out(` ${m === current ? c.brand('●') : c.grey('○')} ${m}`));
|
|
@@ -2834,7 +2834,7 @@ const commands = {
|
|
|
2834
2834
|
sessions: {
|
|
2835
2835
|
summary: 'list saved sessions for this directory',
|
|
2836
2836
|
usage: ['jaitus sessions [--json]'],
|
|
2837
|
-
detail: ['Sessions are stored locally under ~/.jaitus/sessions and never sent to
|
|
2837
|
+
detail: ['Sessions are stored locally under ~/.jaitus/sessions and never sent to Jaitus until resumed.'],
|
|
2838
2838
|
run: (argv, { json, flags }) => {
|
|
2839
2839
|
const data = listSessions({ cwd: flags.cwd }).map(sessionSummary);
|
|
2840
2840
|
present(json, { sessions: data }, () => {
|
|
@@ -2893,7 +2893,7 @@ const commands = {
|
|
|
2893
2893
|
},
|
|
2894
2894
|
|
|
2895
2895
|
config: {
|
|
2896
|
-
summary: 'show or change
|
|
2896
|
+
summary: 'show or change CLI settings',
|
|
2897
2897
|
usage: [
|
|
2898
2898
|
'jaitus config show everything',
|
|
2899
2899
|
'jaitus config model show one value',
|
|
@@ -2944,12 +2944,12 @@ const commands = {
|
|
|
2944
2944
|
configDir: HOME,
|
|
2945
2945
|
};
|
|
2946
2946
|
present(json, data, () => table([
|
|
2947
|
-
['
|
|
2947
|
+
['Server', data.gateway],
|
|
2948
2948
|
['Website', data.website],
|
|
2949
|
-
['Model', data.model || '
|
|
2949
|
+
['Model', data.model || 'automatic — Jaitus picks the model for each request'],
|
|
2950
2950
|
['Theme', `${data.theme} (${[...THEME_NAMES, 'auto'].join(', ')})`],
|
|
2951
2951
|
['Start mode', data.defaultMode || 'the last mode used (ask or auto-edit)'],
|
|
2952
|
-
['Copy on select', data.copyOnSelect ? 'on (drag selects, auto-copies)' : 'off (Ctrl+
|
|
2952
|
+
['Copy on select', data.copyOnSelect ? 'on (drag selects, auto-copies)' : 'off (select, then Ctrl+C copies)'],
|
|
2953
2953
|
['Scroll speed', String(data.scrollSpeed)],
|
|
2954
2954
|
['Wheel accel', data.wheelAccel ? 'on' : 'off'],
|
|
2955
2955
|
['Auto-scroll', data.autoScroll ? 'on' : 'off'],
|
|
@@ -3042,8 +3042,8 @@ const commands = {
|
|
|
3042
3042
|
summary: 'check everything that can stop this working',
|
|
3043
3043
|
usage: ['jaitus doctor [--json]'],
|
|
3044
3044
|
detail: [
|
|
3045
|
-
'Node version, config directory, sign-in,
|
|
3046
|
-
'and whether an update is out. Never prints your
|
|
3045
|
+
'Node version, config directory, sign-in, whether Jaitus can be reached, the account',
|
|
3046
|
+
'and whether an update is out. Never prints your sign-in token — only whether you are signed in.',
|
|
3047
3047
|
],
|
|
3048
3048
|
run: (argv, { json }) => doctor(argv, { json }),
|
|
3049
3049
|
},
|