@lazyingart/agintiflow 0.20.38 → 0.20.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +1 -1
- package/public/app.js +11 -11
- package/public/index.html +1 -1
- package/scripts/smoke-auto-update.js +46 -1
- package/src/auto-update.js +139 -2
- package/src/i18n.js +1 -0
- package/src/interactive-cli.js +2 -0
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ aginti --list-profiles
|
|
|
50
50
|
aginti --sandbox-status
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
When AgInTiFlow is installed globally from npm, normal `aginti`, `aginti chat`, `aginti resume`, and `aginti web` startup checks npm for a newer `@lazyingart/agintiflow` release at a throttled interval. If a newer version is found,
|
|
53
|
+
When AgInTiFlow is installed globally from npm, normal `aginti`, `aginti chat`, `aginti resume`, and `aginti web` startup checks npm for a newer `@lazyingart/agintiflow` release at a throttled interval. If a newer version is found in an interactive terminal, AgInTiFlow shows an Up/Down selector with `Update now`, `Skip this time`, and `Skip this version`; updating runs `npm install -g @lazyingart/agintiflow@latest` and restarts the CLI once. Source checkouts and non-TTY automation skip this behavior. Force a check with `aginti update`, skip one run with `--no-auto-update`, or disable it with `AGINTIFLOW_NO_AUTO_UPDATE=1`.
|
|
54
54
|
|
|
55
55
|
On first interactive use, if no main model key is detected, `aginti` opens an auth wizard. Use Up/Down to choose DeepSeek, OpenAI, Qwen, or Venice, paste the key, and press Enter to save it to the project-local ignored file `.aginti/.env` with `0600` permissions. The wizard points to DeepSeek keys at `https://platform.deepseek.com/api_keys`, OpenAI keys at `https://platform.openai.com/api-keys`, and Venice at `https://venice.ai`. It then offers the optional auxiliary image key; press Esc to skip. You can rerun it even when keys already exist:
|
|
56
56
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.40",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgInTiFlow is a web-first coding agent and CLI with DeepSeek routing, sandboxed tools, model providers, canvas artifacts, and optional wrappers.",
|
|
6
6
|
"license": "Apache-2.0",
|
package/public/app.js
CHANGED
|
@@ -15,7 +15,7 @@ const supportedLanguages = [
|
|
|
15
15
|
const translations = {
|
|
16
16
|
en: {
|
|
17
17
|
documentTitle: "AgInTiFlow",
|
|
18
|
-
brandKicker: "
|
|
18
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
19
19
|
languageLabel: "Language",
|
|
20
20
|
intro:
|
|
21
21
|
"Web-first agent platform with smart model routing, resumable runs, guarded tools, and optional external agent wrappers.",
|
|
@@ -174,7 +174,7 @@ const translations = {
|
|
|
174
174
|
},
|
|
175
175
|
ar: {
|
|
176
176
|
documentTitle: "AgInTiFlow",
|
|
177
|
-
brandKicker: "
|
|
177
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
178
178
|
languageLabel: "اللغة",
|
|
179
179
|
intro:
|
|
180
180
|
"وكيل متصفح مع اختيار المزوّد، تشغيل قابل للاستئناف، إعدادات محفوظة، وأداة shell محمية اختيارية مع دعم Docker sandbox.",
|
|
@@ -221,7 +221,7 @@ const translations = {
|
|
|
221
221
|
},
|
|
222
222
|
es: {
|
|
223
223
|
documentTitle: "AgInTiFlow",
|
|
224
|
-
brandKicker: "
|
|
224
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
225
225
|
languageLabel: "Idioma",
|
|
226
226
|
intro:
|
|
227
227
|
"Agente de navegador con selección de proveedor, ejecuciones reanudables, ajustes persistentes y shell protegido opcional con Docker sandbox.",
|
|
@@ -268,7 +268,7 @@ const translations = {
|
|
|
268
268
|
},
|
|
269
269
|
fr: {
|
|
270
270
|
documentTitle: "AgInTiFlow",
|
|
271
|
-
brandKicker: "
|
|
271
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
272
272
|
languageLabel: "Langue",
|
|
273
273
|
intro:
|
|
274
274
|
"Agent navigateur avec choix du fournisseur, runs reprenables, réglages persistants et outil shell gardé optionnel avec Docker sandbox.",
|
|
@@ -315,7 +315,7 @@ const translations = {
|
|
|
315
315
|
},
|
|
316
316
|
ja: {
|
|
317
317
|
documentTitle: "AgInTiFlow",
|
|
318
|
-
brandKicker: "AgInTi
|
|
318
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
319
319
|
languageLabel: "言語",
|
|
320
320
|
intro:
|
|
321
321
|
"プロバイダー選択、再開可能な実行、保存される設定、Docker sandbox対応の保護されたshellツールを備えたブラウザエージェントです。",
|
|
@@ -362,7 +362,7 @@ const translations = {
|
|
|
362
362
|
},
|
|
363
363
|
ko: {
|
|
364
364
|
documentTitle: "AgInTiFlow",
|
|
365
|
-
brandKicker: "AgInTi
|
|
365
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
366
366
|
languageLabel: "언어",
|
|
367
367
|
intro:
|
|
368
368
|
"제공자 선택, 재개 가능한 실행, 저장되는 설정, Docker sandbox 지원 보호 shell 도구를 갖춘 브라우저 에이전트입니다.",
|
|
@@ -409,7 +409,7 @@ const translations = {
|
|
|
409
409
|
},
|
|
410
410
|
vi: {
|
|
411
411
|
documentTitle: "AgInTiFlow",
|
|
412
|
-
brandKicker: "
|
|
412
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
413
413
|
languageLabel: "Ngôn ngữ",
|
|
414
414
|
intro:
|
|
415
415
|
"Agent trình duyệt có chọn provider, phiên chạy tiếp tục được, cài đặt được lưu, và shell tool được bảo vệ tùy chọn với Docker sandbox.",
|
|
@@ -456,7 +456,7 @@ const translations = {
|
|
|
456
456
|
},
|
|
457
457
|
"zh-Hans": {
|
|
458
458
|
documentTitle: "AgInTiFlow",
|
|
459
|
-
brandKicker: "AgInTi
|
|
459
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
460
460
|
languageLabel: "语言",
|
|
461
461
|
intro:
|
|
462
462
|
"浏览器智能体,支持模型供应商选择、可恢复运行、持久设置,以及可选的受保护 shell 工具和 Docker 沙箱。",
|
|
@@ -503,7 +503,7 @@ const translations = {
|
|
|
503
503
|
},
|
|
504
504
|
"zh-Hant": {
|
|
505
505
|
documentTitle: "AgInTiFlow",
|
|
506
|
-
brandKicker: "AgInTi
|
|
506
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
507
507
|
languageLabel: "語言",
|
|
508
508
|
intro:
|
|
509
509
|
"瀏覽器智能體,支援模型供應商選擇、可恢復執行、持久設定,以及可選的受保護 shell 工具與 Docker 沙箱。",
|
|
@@ -550,7 +550,7 @@ const translations = {
|
|
|
550
550
|
},
|
|
551
551
|
de: {
|
|
552
552
|
documentTitle: "AgInTiFlow",
|
|
553
|
-
brandKicker: "
|
|
553
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
554
554
|
languageLabel: "Sprache",
|
|
555
555
|
intro:
|
|
556
556
|
"Browser-Agent mit Provider-Auswahl, fortsetzbaren Läufen, gespeicherten Einstellungen und optional geschütztem Shell-Tool mit Docker-Sandbox.",
|
|
@@ -597,7 +597,7 @@ const translations = {
|
|
|
597
597
|
},
|
|
598
598
|
ru: {
|
|
599
599
|
documentTitle: "AgInTiFlow",
|
|
600
|
-
brandKicker: "
|
|
600
|
+
brandKicker: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
601
601
|
languageLabel: "Язык",
|
|
602
602
|
intro:
|
|
603
603
|
"Браузерный агент с выбором провайдера, возобновляемыми запусками, сохраненными настройками и опциональным защищенным shell tool с Docker sandbox.",
|
package/public/index.html
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<img class="brand-logo" src="/logos/logo.png" alt="AgInTiFlow logo" />
|
|
15
15
|
<div>
|
|
16
16
|
<h1>AgInTiFlow</h1>
|
|
17
|
-
<p class="brand-kicker" data-i18n="brandKicker">
|
|
17
|
+
<p class="brand-kicker" data-i18n="brandKicker">Developed by AgInTi Lab, LazyingArt LLC</p>
|
|
18
18
|
</div>
|
|
19
19
|
<label class="language-switch">
|
|
20
20
|
<span data-i18n="languageLabel">Language</span>
|
|
@@ -6,6 +6,9 @@ import {
|
|
|
6
6
|
maybeAutoUpdate,
|
|
7
7
|
shouldAutoUpdateCommand,
|
|
8
8
|
} from "../src/auto-update.js";
|
|
9
|
+
import fs from "node:fs/promises";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
import path from "node:path";
|
|
9
12
|
|
|
10
13
|
function assert(condition, message) {
|
|
11
14
|
if (!condition) throw new Error(message);
|
|
@@ -47,5 +50,47 @@ const skipped = await maybeAutoUpdate({
|
|
|
47
50
|
});
|
|
48
51
|
assert(skipped.skipped === "source-checkout", "source checkout update guard failed");
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "agintiflow-auto-update-"));
|
|
54
|
+
const previousHome = process.env.AGINTIFLOW_HOME;
|
|
55
|
+
process.env.AGINTIFLOW_HOME = tempHome;
|
|
56
|
+
await fs.mkdir(tempHome, { recursive: true });
|
|
57
|
+
await fs.writeFile(
|
|
58
|
+
path.join(tempHome, "update-check.json"),
|
|
59
|
+
`${JSON.stringify({ checkedAt: Date.now(), latest: "0.20.99" })}\n`,
|
|
60
|
+
"utf8"
|
|
61
|
+
);
|
|
62
|
+
const writes = [];
|
|
63
|
+
const fakeStdout = {
|
|
64
|
+
isTTY: true,
|
|
65
|
+
write(value) {
|
|
66
|
+
writes.push(String(value));
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
const skipVersion = await maybeAutoUpdate({
|
|
70
|
+
argv: [],
|
|
71
|
+
packageDir: scopedGlobalPath,
|
|
72
|
+
packageName: "@lazyingart/agintiflow",
|
|
73
|
+
packageVersion: "0.20.38",
|
|
74
|
+
restart: false,
|
|
75
|
+
stdout: fakeStdout,
|
|
76
|
+
selectUpdateAction: async () => "skip-version",
|
|
77
|
+
});
|
|
78
|
+
assert(skipVersion.skipped === "skip-version", "skip-version selector choice was not honored");
|
|
79
|
+
const cacheAfterSkip = JSON.parse(await fs.readFile(path.join(tempHome, "update-check.json"), "utf8"));
|
|
80
|
+
assert(cacheAfterSkip.skippedVersion === "0.20.99", "skip-version did not persist skipped version");
|
|
81
|
+
const repeatedSkip = await maybeAutoUpdate({
|
|
82
|
+
argv: [],
|
|
83
|
+
packageDir: scopedGlobalPath,
|
|
84
|
+
packageName: "@lazyingart/agintiflow",
|
|
85
|
+
packageVersion: "0.20.38",
|
|
86
|
+
restart: false,
|
|
87
|
+
stdout: fakeStdout,
|
|
88
|
+
selectUpdateAction: async () => {
|
|
89
|
+
throw new Error("selector should not be called after skip-version");
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
assert(repeatedSkip.skipped === "skipped-version", "cached skipped version was not respected");
|
|
93
|
+
if (previousHome === undefined) delete process.env.AGINTIFLOW_HOME;
|
|
94
|
+
else process.env.AGINTIFLOW_HOME = previousHome;
|
|
51
95
|
|
|
96
|
+
console.log("auto-update smoke ok");
|
package/src/auto-update.js
CHANGED
|
@@ -2,12 +2,30 @@ import { execFile, spawn } from "node:child_process";
|
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import readline from "node:readline";
|
|
5
6
|
import { promisify } from "node:util";
|
|
6
7
|
|
|
7
8
|
const execFileAsync = promisify(execFile);
|
|
8
9
|
const DEFAULT_PACKAGE_NAME = "@lazyingart/agintiflow";
|
|
9
10
|
const DEFAULT_CHECK_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
10
11
|
const DEFAULT_FAILURE_RETRY_MS = 6 * 60 * 60 * 1000;
|
|
12
|
+
const UPDATE_CHOICES = [
|
|
13
|
+
{
|
|
14
|
+
id: "update",
|
|
15
|
+
label: "Update now",
|
|
16
|
+
description: "Install latest globally, then restart AgInTiFlow.",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
id: "skip-once",
|
|
20
|
+
label: "Skip this time",
|
|
21
|
+
description: "Continue with the current version for this run.",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: "skip-version",
|
|
25
|
+
label: "Skip this version",
|
|
26
|
+
description: "Do not ask again until a newer release appears.",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
11
29
|
const START_COMMANDS = new Set(["", "chat", "interactive", "resume", "web", "--web", "--chat", "--interactive"]);
|
|
12
30
|
const SKIP_COMMANDS = new Set([
|
|
13
31
|
"auth",
|
|
@@ -115,12 +133,16 @@ function nowMs() {
|
|
|
115
133
|
}
|
|
116
134
|
|
|
117
135
|
function checkIntervalMs() {
|
|
118
|
-
const
|
|
136
|
+
const raw = process.env.AGINTIFLOW_AUTO_UPDATE_INTERVAL_MS;
|
|
137
|
+
if (raw === undefined || raw === "") return DEFAULT_CHECK_INTERVAL_MS;
|
|
138
|
+
const value = Number(raw);
|
|
119
139
|
return Number.isFinite(value) && value >= 0 ? value : DEFAULT_CHECK_INTERVAL_MS;
|
|
120
140
|
}
|
|
121
141
|
|
|
122
142
|
function failureRetryMs() {
|
|
123
|
-
const
|
|
143
|
+
const raw = process.env.AGINTIFLOW_AUTO_UPDATE_FAILURE_RETRY_MS;
|
|
144
|
+
if (raw === undefined || raw === "") return DEFAULT_FAILURE_RETRY_MS;
|
|
145
|
+
const value = Number(raw);
|
|
124
146
|
return Number.isFinite(value) && value >= 0 ? value : DEFAULT_FAILURE_RETRY_MS;
|
|
125
147
|
}
|
|
126
148
|
|
|
@@ -158,6 +180,91 @@ function shouldSkipFailedInstall(cache, currentMs, force) {
|
|
|
158
180
|
return failedAt > 0 && currentMs - failedAt < failureRetryMs();
|
|
159
181
|
}
|
|
160
182
|
|
|
183
|
+
function renderUpdateSelector(output, { current, latest, packageName, selectedIndex, renderedLines }) {
|
|
184
|
+
const rows = [
|
|
185
|
+
`AgInTiFlow update available: ${current} -> ${latest}`,
|
|
186
|
+
`Package: ${packageName}`,
|
|
187
|
+
"Use Up/Down to choose, Enter to confirm, Esc to skip.",
|
|
188
|
+
"",
|
|
189
|
+
...UPDATE_CHOICES.map((choice, index) => {
|
|
190
|
+
const cursor = index === selectedIndex ? ">" : " ";
|
|
191
|
+
return `${cursor} ${choice.label.padEnd(17)} ${choice.description}`;
|
|
192
|
+
}),
|
|
193
|
+
];
|
|
194
|
+
if (renderedLines > 0) output.write(`\x1b[${renderedLines}A\x1b[J`);
|
|
195
|
+
output.write(`${rows.join("\n")}\n`);
|
|
196
|
+
return rows.length;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export async function promptUpdateChoice({
|
|
200
|
+
current = "",
|
|
201
|
+
latest = "",
|
|
202
|
+
packageName = DEFAULT_PACKAGE_NAME,
|
|
203
|
+
input = process.stdin,
|
|
204
|
+
output = process.stdout,
|
|
205
|
+
} = {}) {
|
|
206
|
+
if (!input.isTTY || !output.isTTY || typeof input.setRawMode !== "function") return "skip-once";
|
|
207
|
+
|
|
208
|
+
readline.emitKeypressEvents(input);
|
|
209
|
+
const wasRaw = input.isRaw;
|
|
210
|
+
let renderedLines = 0;
|
|
211
|
+
let selectedIndex = 0;
|
|
212
|
+
let resolved = false;
|
|
213
|
+
|
|
214
|
+
return await new Promise((resolve) => {
|
|
215
|
+
function finish(choice) {
|
|
216
|
+
if (resolved) return;
|
|
217
|
+
resolved = true;
|
|
218
|
+
input.off("keypress", onKeypress);
|
|
219
|
+
input.setRawMode(Boolean(wasRaw));
|
|
220
|
+
if (!wasRaw) input.pause();
|
|
221
|
+
output.write("\n");
|
|
222
|
+
resolve(choice);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function render() {
|
|
226
|
+
renderedLines = renderUpdateSelector(output, {
|
|
227
|
+
current,
|
|
228
|
+
latest,
|
|
229
|
+
packageName,
|
|
230
|
+
selectedIndex,
|
|
231
|
+
renderedLines,
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function onKeypress(_chunk, key = {}) {
|
|
236
|
+
if (key.ctrl && key.name === "c") {
|
|
237
|
+
input.setRawMode(Boolean(wasRaw));
|
|
238
|
+
if (!wasRaw) input.pause();
|
|
239
|
+
output.write("\n");
|
|
240
|
+
process.exit(130);
|
|
241
|
+
}
|
|
242
|
+
if (key.name === "up" || key.name === "left") {
|
|
243
|
+
selectedIndex = (selectedIndex - 1 + UPDATE_CHOICES.length) % UPDATE_CHOICES.length;
|
|
244
|
+
render();
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (key.name === "down" || key.name === "right" || key.name === "tab") {
|
|
248
|
+
selectedIndex = (selectedIndex + 1) % UPDATE_CHOICES.length;
|
|
249
|
+
render();
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (key.name === "return" || key.name === "enter") {
|
|
253
|
+
finish(UPDATE_CHOICES[selectedIndex].id);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (key.name === "escape") {
|
|
257
|
+
finish("skip-once");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
input.setRawMode(true);
|
|
262
|
+
input.resume();
|
|
263
|
+
render();
|
|
264
|
+
input.on("keypress", onKeypress);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
161
268
|
export async function maybeAutoUpdate({
|
|
162
269
|
argv = [],
|
|
163
270
|
force = false,
|
|
@@ -166,6 +273,7 @@ export async function maybeAutoUpdate({
|
|
|
166
273
|
packageName = DEFAULT_PACKAGE_NAME,
|
|
167
274
|
packageVersion = "",
|
|
168
275
|
restart = false,
|
|
276
|
+
selectUpdateAction = promptUpdateChoice,
|
|
169
277
|
stdout = process.stdout,
|
|
170
278
|
stderr = process.stderr,
|
|
171
279
|
} = {}) {
|
|
@@ -214,6 +322,35 @@ export async function maybeAutoUpdate({
|
|
|
214
322
|
return { checked: true, latest, current: packageVersion, updated: false, skipped: "recent-install-failure" };
|
|
215
323
|
}
|
|
216
324
|
|
|
325
|
+
if (!manual && !force) {
|
|
326
|
+
if (cache.skippedVersion === latest) {
|
|
327
|
+
return { checked: true, latest, current: packageVersion, updated: false, skipped: "skipped-version" };
|
|
328
|
+
}
|
|
329
|
+
const choice = await selectUpdateAction({
|
|
330
|
+
current: packageVersion,
|
|
331
|
+
latest,
|
|
332
|
+
packageName,
|
|
333
|
+
input: process.stdin,
|
|
334
|
+
output: stdout,
|
|
335
|
+
});
|
|
336
|
+
if (choice === "skip-version") {
|
|
337
|
+
await writeCache({
|
|
338
|
+
...cache,
|
|
339
|
+
checkedAt: currentMs,
|
|
340
|
+
latest,
|
|
341
|
+
skippedVersion: latest,
|
|
342
|
+
skippedAt: currentMs,
|
|
343
|
+
packageName,
|
|
344
|
+
});
|
|
345
|
+
stdout.write(`Skipped AgInTiFlow ${latest}. Run \`aginti update\` to install it later.\n`);
|
|
346
|
+
return { checked: true, latest, current: packageVersion, updated: false, skipped: "skip-version" };
|
|
347
|
+
}
|
|
348
|
+
if (choice !== "update") {
|
|
349
|
+
stdout.write(`Skipped update for this run. Run \`aginti update\` to install ${latest} later.\n`);
|
|
350
|
+
return { checked: true, latest, current: packageVersion, updated: false, skipped: "skip-once" };
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
217
354
|
stdout.write(`AgInTiFlow update available: ${packageVersion} -> ${latest}\n`);
|
|
218
355
|
stdout.write(`Running: npm install -g ${packageName}@latest\n`);
|
|
219
356
|
const install = await installLatest(packageName);
|
package/src/i18n.js
CHANGED
|
@@ -114,6 +114,7 @@ const LANGUAGE_ALIASES = new Map(
|
|
|
114
114
|
const TRANSLATIONS = {
|
|
115
115
|
en: {
|
|
116
116
|
launchSubtitle: "web-first agent workspace",
|
|
117
|
+
launchCredit: "Developed by AgInTi Lab, LazyingArt LLC",
|
|
117
118
|
launchTagline: "browser + shell + files + docker + web search + scouts",
|
|
118
119
|
interactiveIntro: "Interactive agent chat. Type /help for commands, /exit to quit.",
|
|
119
120
|
promptEmpty: "type a request, /help, Enter to send, Ctrl+J for newline",
|
package/src/interactive-cli.js
CHANGED
|
@@ -567,6 +567,7 @@ function launchTitleLines(contentWidth) {
|
|
|
567
567
|
|
|
568
568
|
export function buildLaunchHeaderLines({ packageVersion = "", frame = 2, width = terminalWidth(), animated = true, language = cliLanguage } = {}) {
|
|
569
569
|
const subtitle = t("launchSubtitle", language);
|
|
570
|
+
const credit = t("launchCredit", language);
|
|
570
571
|
const tagline = t("launchTagline", language);
|
|
571
572
|
const version = packageVersion ? `v${packageVersion}` : "";
|
|
572
573
|
const terminalColumns = Math.max(Number(width) || 80, 50);
|
|
@@ -584,6 +585,7 @@ export function buildLaunchHeaderLines({ packageVersion = "", frame = 2, width =
|
|
|
584
585
|
...titleLines.map((line) => row(line)),
|
|
585
586
|
versionLine ? row(versionLine) : "",
|
|
586
587
|
row(centerLine(subtitle, contentWidth), ansi.dim),
|
|
588
|
+
row(centerLine(credit, contentWidth), ansi.dim),
|
|
587
589
|
mid,
|
|
588
590
|
row(centerLine(tagline, contentWidth), ansi.cyan),
|
|
589
591
|
bottom,
|