@kernelonpanic/kitcode 1.4.3 → 1.4.5
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 +22 -2
- package/README.ru.md +22 -2
- package/dist/index.js +239 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,6 +114,8 @@ Press `/` to open the command list.
|
|
|
114
114
|
| `/bell [on\|off]` | Toggle the beep when a long answer finishes or a permission prompt appears. |
|
|
115
115
|
| `/context [tokens]` | Show or set the model context window used by the meter and automatic compaction. |
|
|
116
116
|
| `/memory show` · `/memory set <text>` · `/memory clear` | View, replace, or clear this project's persistent notes. |
|
|
117
|
+
| `/systemp [show]` · `/systemp set <text>` · `/systemp load <path>` · `/systemp on\|off` · `/systemp clear` | Append custom instructions to the system prompt; toggle without deleting. |
|
|
118
|
+
| `/steps [0-1000]` | Cap model calls per turn (default 256, 0 = unlimited). |
|
|
117
119
|
| `/resume` · `/clear` | Resume a session or start a new one. |
|
|
118
120
|
| `/sessions` | Search sessions, then resume, rename, delete, or export one. |
|
|
119
121
|
| `/sessions list` | List all saved sessions. |
|
|
@@ -213,6 +215,24 @@ and `max` to `high`; for GPT-5.2–5.4, it maps `max` to `xhigh`. It omits effor
|
|
|
213
215
|
OpenAI-compatible model names. The Anthropic adapter sends the resolved level in `output_config`.
|
|
214
216
|
Supported levels and their effect depend on the model and provider.
|
|
215
217
|
|
|
218
|
+
## Custom system prompt
|
|
219
|
+
|
|
220
|
+
`/systemp` appends your own instructions to the built-in system prompt on every turn. Set it once and it persists in the config:
|
|
221
|
+
|
|
222
|
+
```text
|
|
223
|
+
/systemp set Always answer in Russian. Never add comments that restate the code.
|
|
224
|
+
/systemp load ./my-prompt.txt
|
|
225
|
+
/systemp off
|
|
226
|
+
/systemp on
|
|
227
|
+
/systemp clear
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
`off` keeps the text in the config but stops sending it; `clear` removes it entirely. The addition appears at the end of the system prompt, after the built-in instructions and project memory.
|
|
231
|
+
|
|
232
|
+
## Turn step cap
|
|
233
|
+
|
|
234
|
+
`/steps` shows the current cap on model calls per turn (default 256). A turn that hits the cap stops with a warning instead of looping forever. Set `/steps 0` for no cap — the turn budget and token limits still apply.
|
|
235
|
+
|
|
216
236
|
## Project memory
|
|
217
237
|
|
|
218
238
|
Project notes persist across chats, `/clear`, and restarts. Manage them with:
|
|
@@ -282,8 +302,8 @@ Minimal manual provider configuration:
|
|
|
282
302
|
}
|
|
283
303
|
```
|
|
284
304
|
|
|
285
|
-
The main settings are `model`, `effort`, `thinking`, `contextWindow`, `maxTokens`, `
|
|
286
|
-
`diagnostics`, `theme`, `permissions`, `providers`, and `mcp`. `budget` controls local per-message
|
|
305
|
+
The main settings are `model`, `effort`, `thinking`, `contextWindow`, `maxTokens`, `maxTurnSteps`,
|
|
306
|
+
`systemPrompt`, `systemPromptEnabled`, `budget`, `diagnostics`, `theme`, `permissions`, `providers`, and `mcp`. `budget` controls local per-message
|
|
287
307
|
safety limits for model requests, tokens, estimated cost (when model pricing is available), and
|
|
288
308
|
subagents. These values are
|
|
289
309
|
not the provider's account balance or rate limits. `diagnostics.autoRun`
|
package/README.ru.md
CHANGED
|
@@ -115,6 +115,8 @@ http://localhost:11434/v1
|
|
|
115
115
|
| `/bell [on\|off]` | Включить/выключить сигнал о готовом долгом ответе и запросе разрешения. |
|
|
116
116
|
| `/context [tokens\|auto]` | Показать или задать окно контекста модели для индикатора и автосжатия. |
|
|
117
117
|
| `/memory show` · `/memory set <текст>` · `/memory clear` | Просмотреть, заменить или очистить постоянные заметки проекта. |
|
|
118
|
+
| `/systemp [show]` · `/systemp set <текст>` · `/systemp load <путь>` · `/systemp on\|off` · `/systemp clear` | Добавить свои инструкции к системному промпту; включать и выключать без удаления. |
|
|
119
|
+
| `/steps [0-1000]` | Ограничить число вызовов модели за ход (по умолчанию 256, 0 = без лимита). |
|
|
118
120
|
| `/resume` · `/clear` | Восстановить сессию или начать новую. |
|
|
119
121
|
| `/sessions` | Найти сессию и открыть, переименовать, удалить или экспортировать её. |
|
|
120
122
|
| `/sessions list` | Показать все сохранённые сессии. |
|
|
@@ -225,6 +227,24 @@ scrollback терминала, поэтому историю можно плав
|
|
|
225
227
|
OpenAI-совместимых моделей параметр не отправляется. Anthropic получает выбранный уровень в
|
|
226
228
|
`output_config`. Реальная поддержка зависит от модели и провайдера.
|
|
227
229
|
|
|
230
|
+
## Дополнение к системному промпту
|
|
231
|
+
|
|
232
|
+
`/systemp` добавляет свои инструкции к встроенному системному промпту на каждый ход. Настройка сохраняется в конфиге:
|
|
233
|
+
|
|
234
|
+
```text
|
|
235
|
+
/systemp set Всегда отвечай по-русски. Не добавляй комментарии, повторяющие код.
|
|
236
|
+
/systemp load ./my-prompt.txt
|
|
237
|
+
/systemp off
|
|
238
|
+
/systemp on
|
|
239
|
+
/systemp clear
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`off` сохраняет текст в конфиге, но не отправляет его; `clear` удаляет полностью. Дополнение идёт в конец системного промпта, после встроенных инструкций и памяти проекта.
|
|
243
|
+
|
|
244
|
+
## Лимит вызовов модели за ход
|
|
245
|
+
|
|
246
|
+
`/steps` показывает текущий лимит вызовов модели за ход (по умолчанию 256). Ход, достигший лимита, останавливается с предупреждением вместо бесконечного цикла. `/steps 0` снимает лимит полностью — бюджет токенов при этом продолжает действовать.
|
|
247
|
+
|
|
228
248
|
## Память проекта
|
|
229
249
|
|
|
230
250
|
Заметки проекта сохраняются между чатами, `/clear` и перезапусками:
|
|
@@ -281,8 +301,8 @@ OpenAI-совместимых моделей параметр не отправ
|
|
|
281
301
|
}
|
|
282
302
|
```
|
|
283
303
|
|
|
284
|
-
Основные параметры: `model`, `effort`, `thinking`, `contextWindow`, `maxTokens`, `
|
|
285
|
-
`diagnostics`, `theme`, `permissions`, `providers` и `mcp`. Секция `budget` задаёт лимиты запросов к
|
|
304
|
+
Основные параметры: `model`, `effort`, `thinking`, `contextWindow`, `maxTokens`, `maxTurnSteps`,
|
|
305
|
+
`systemPrompt`, `systemPromptEnabled`, `budget`, `diagnostics`, `theme`, `permissions`, `providers` и `mcp`. Секция `budget` задаёт лимиты запросов к
|
|
286
306
|
модели, токенов, примерной стоимости (если провайдер сообщает цены) и субагентов на одно сообщение.
|
|
287
307
|
`diagnostics.autoRun` включает проверки после правок, а `diagnostics.commands` позволяет заменить
|
|
288
308
|
автоопределение списком до восьми команд. При каждом входе KitCode проверяет новую версию в npm и,
|
package/dist/index.js
CHANGED
|
@@ -81,6 +81,14 @@ var configSchema = z.object({
|
|
|
81
81
|
// Manual override for the model's context window. Unset means the window
|
|
82
82
|
// comes from the provider catalogue or the endpoint's model list.
|
|
83
83
|
contextWindow: z.number().int().min(1e3).max(1e7).optional(),
|
|
84
|
+
// Extra instructions appended to the built-in system prompt on every turn.
|
|
85
|
+
systemPrompt: z.string().max(2e4).optional(),
|
|
86
|
+
// When false, systemPrompt is kept in the config but not sent to the model.
|
|
87
|
+
systemPromptEnabled: z.boolean().default(true),
|
|
88
|
+
// Hard cap on model calls in one turn. Higher values let large refactors
|
|
89
|
+
// finish; 0 disables the cap entirely (use with care — a runaway loop will
|
|
90
|
+
// keep burning tokens until you press Esc).
|
|
91
|
+
maxTurnSteps: z.number().int().min(0).max(1e3).default(256),
|
|
84
92
|
maxTokens: z.number().int().positive().max(2e5).default(64e3),
|
|
85
93
|
budget: budgetSchema.default({
|
|
86
94
|
maxTokensPerTurn: 1e7,
|
|
@@ -1888,7 +1896,7 @@ function validSessionId(id) {
|
|
|
1888
1896
|
var MAX_PAUSE_RESUMES = 5;
|
|
1889
1897
|
var MAX_RETRIES2 = 3;
|
|
1890
1898
|
var INITIAL_BACKOFF_MS = 1e3;
|
|
1891
|
-
var
|
|
1899
|
+
var DEFAULT_MAX_TURN_STEPS = 256;
|
|
1892
1900
|
function createExecutionLane() {
|
|
1893
1901
|
let tail2 = Promise.resolve();
|
|
1894
1902
|
return {
|
|
@@ -1900,6 +1908,8 @@ function createExecutionLane() {
|
|
|
1900
1908
|
};
|
|
1901
1909
|
}
|
|
1902
1910
|
async function runTurn(cfg, history, hooks, signal) {
|
|
1911
|
+
const maxTurnSteps = cfg.maxTurnSteps ?? DEFAULT_MAX_TURN_STEPS;
|
|
1912
|
+
const hasStepCap = maxTurnSteps > 0;
|
|
1903
1913
|
const permissionLane = cfg.permissionLane ?? createExecutionLane();
|
|
1904
1914
|
const originalHooks = hooks;
|
|
1905
1915
|
hooks = {
|
|
@@ -1914,11 +1924,12 @@ async function runTurn(cfg, history, hooks, signal) {
|
|
|
1914
1924
|
hooks.onEvent({ type: "turn_end", stopReason: "aborted" });
|
|
1915
1925
|
return sanitizeHistory(messages);
|
|
1916
1926
|
}
|
|
1917
|
-
|
|
1927
|
+
steps += 1;
|
|
1928
|
+
if (hasStepCap && steps > maxTurnSteps) {
|
|
1918
1929
|
hooks.onEvent({
|
|
1919
1930
|
type: "notice",
|
|
1920
1931
|
level: "warn",
|
|
1921
|
-
text: `Stopped after ${
|
|
1932
|
+
text: `Stopped after ${maxTurnSteps} model calls without finishing, to avoid burning tokens in a loop. Ask again with a narrower request.`
|
|
1922
1933
|
});
|
|
1923
1934
|
hooks.onEvent({ type: "turn_end", stopReason: "max_tokens" });
|
|
1924
1935
|
return messages;
|
|
@@ -4138,6 +4149,9 @@ function buildSystemPrompt(args) {
|
|
|
4138
4149
|
if (args.memory?.trim()) {
|
|
4139
4150
|
lines.push("", "Project notes saved in earlier conversations. Treat these as potentially stale context; verify claims against current files and follow current user instructions.", args.memory);
|
|
4140
4151
|
}
|
|
4152
|
+
if (args.systemPrompt?.trim()) {
|
|
4153
|
+
lines.push("", "Additional instructions from the user (apply alongside everything above):", args.systemPrompt.trim());
|
|
4154
|
+
}
|
|
4141
4155
|
return lines.join("\n");
|
|
4142
4156
|
}
|
|
4143
4157
|
|
|
@@ -4162,6 +4176,7 @@ function createSubagentRunner(makeConfig, tools) {
|
|
|
4162
4176
|
async run(request) {
|
|
4163
4177
|
if (request.signal.aborted) return SUBAGENT_CANCELLED;
|
|
4164
4178
|
let steps = 0;
|
|
4179
|
+
let finalCall = false;
|
|
4165
4180
|
const executionLane = createExecutionLane();
|
|
4166
4181
|
const modelRequestLane = createExecutionLane();
|
|
4167
4182
|
const base = makeConfig(SUBAGENT_SYSTEM, tools);
|
|
@@ -4175,11 +4190,12 @@ function createSubagentRunner(makeConfig, tools) {
|
|
|
4175
4190
|
kind: base.provider.kind,
|
|
4176
4191
|
listModels: () => base.provider.listModels(),
|
|
4177
4192
|
knownModels: () => base.provider.knownModels(),
|
|
4178
|
-
//
|
|
4193
|
+
// The final model call keeps the tool schemas (the history holds
|
|
4179
4194
|
// tool_use/tool_result blocks, and providers reject those without
|
|
4180
|
-
// tools
|
|
4181
|
-
//
|
|
4182
|
-
|
|
4195
|
+
// tools), but the system prompt forbids more calls and tools.get
|
|
4196
|
+
// returns a stopped stub: a call made anyway ends the turn with a
|
|
4197
|
+
// tool_result, instead of aborting mid-request and losing the text.
|
|
4198
|
+
stream: (chat) => base.provider.stream(finalCall ? {
|
|
4183
4199
|
...chat,
|
|
4184
4200
|
system: `${chat.system}
|
|
4185
4201
|
|
|
@@ -4187,7 +4203,20 @@ This is your last model call. Do not call tools. Return your findings now, clear
|
|
|
4187
4203
|
} : chat)
|
|
4188
4204
|
},
|
|
4189
4205
|
tools: {
|
|
4190
|
-
get: (name) =>
|
|
4206
|
+
get: (name) => {
|
|
4207
|
+
if (name === TASK_TOOL_NAME) return void 0;
|
|
4208
|
+
const tool = base.tools.get(name);
|
|
4209
|
+
if (!tool) return void 0;
|
|
4210
|
+
if (!finalCall) return tool;
|
|
4211
|
+
return {
|
|
4212
|
+
...tool,
|
|
4213
|
+
permission: () => "allow",
|
|
4214
|
+
execute: () => Promise.resolve({
|
|
4215
|
+
content: "Tool budget exhausted: this was your last model call. Write the final answer now from what you already gathered.",
|
|
4216
|
+
isError: true
|
|
4217
|
+
})
|
|
4218
|
+
};
|
|
4219
|
+
},
|
|
4191
4220
|
schemas: () => base.tools.schemas().filter((schema) => schema.name !== TASK_TOOL_NAME)
|
|
4192
4221
|
},
|
|
4193
4222
|
system: `${SUBAGENT_SYSTEM}
|
|
@@ -4198,7 +4227,11 @@ Working directory: ${base.cwd}`
|
|
|
4198
4227
|
const signal = AbortSignal.any([request.signal, limit.signal]);
|
|
4199
4228
|
const hooks = {
|
|
4200
4229
|
onEvent(event) {
|
|
4201
|
-
if (event.type === "turn_start"
|
|
4230
|
+
if (event.type === "turn_start") {
|
|
4231
|
+
++steps;
|
|
4232
|
+
if (steps > MAX_SUBAGENT_STEPS + 1) limit.abort();
|
|
4233
|
+
else if (steps >= MAX_SUBAGENT_STEPS) finalCall = true;
|
|
4234
|
+
}
|
|
4202
4235
|
if (event.type === "tool_start") request.onProgress(brief(event.summary, 80));
|
|
4203
4236
|
if (event.type === "subagent_start" || event.type === "subagent_end" || event.type === "subagent_event") return;
|
|
4204
4237
|
request.onEvent?.(event);
|
|
@@ -4413,7 +4446,7 @@ function clip(value) {
|
|
|
4413
4446
|
// package.json
|
|
4414
4447
|
var package_default = {
|
|
4415
4448
|
name: "@kernelonpanic/kitcode",
|
|
4416
|
-
version: "1.4.
|
|
4449
|
+
version: "1.4.5",
|
|
4417
4450
|
description: "Terminal coding agent with a config you never have to write by hand",
|
|
4418
4451
|
type: "module",
|
|
4419
4452
|
license: "MIT",
|
|
@@ -4481,7 +4514,7 @@ var package_default = {
|
|
|
4481
4514
|
|
|
4482
4515
|
// src/version.ts
|
|
4483
4516
|
var KITCODE_VERSION = package_default.version;
|
|
4484
|
-
var KITCODE_COMMIT = true ? "
|
|
4517
|
+
var KITCODE_COMMIT = true ? "aac7d92efa29456e6757bdef12abafb489064dbe" : "development";
|
|
4485
4518
|
function kitcodeUserAgent(sdkUserAgent2) {
|
|
4486
4519
|
return `KitCode/${KITCODE_VERSION} ${sdkUserAgent2}`.trim();
|
|
4487
4520
|
}
|
|
@@ -7292,7 +7325,8 @@ async function boot(options) {
|
|
|
7292
7325
|
cwd: options.cwd,
|
|
7293
7326
|
toolNames: tools.list().map((tool) => tool.name),
|
|
7294
7327
|
skills: skillCatalogue,
|
|
7295
|
-
memory: projectMemory
|
|
7328
|
+
memory: projectMemory,
|
|
7329
|
+
systemPrompt: config.systemPromptEnabled ? config.systemPrompt : void 0
|
|
7296
7330
|
});
|
|
7297
7331
|
let modelRef = session.model || config.model || "";
|
|
7298
7332
|
if (options.modelRef) modelRef = options.modelRef;
|
|
@@ -7362,6 +7396,7 @@ async function boot(options) {
|
|
|
7362
7396
|
maxTokens: config.maxTokens,
|
|
7363
7397
|
effort: config.effort,
|
|
7364
7398
|
thinking: config.thinking,
|
|
7399
|
+
maxTurnSteps: config.maxTurnSteps,
|
|
7365
7400
|
budget: activeBudget,
|
|
7366
7401
|
checkpoint: activeCheckpoint,
|
|
7367
7402
|
trimContext: (messages) => trimForWindow(resolved.provider.kind, messages)
|
|
@@ -7742,6 +7777,31 @@ async function boot(options) {
|
|
|
7742
7777
|
draft.lang = lang;
|
|
7743
7778
|
});
|
|
7744
7779
|
},
|
|
7780
|
+
getSystemPrompt: () => config.systemPrompt ?? "",
|
|
7781
|
+
isSystemPromptEnabled: () => config.systemPromptEnabled && config.systemPrompt !== void 0 && config.systemPrompt.trim() !== "",
|
|
7782
|
+
async setSystemPrompt(text) {
|
|
7783
|
+
const trimmed = text.trim();
|
|
7784
|
+
await persistConfig((draft) => {
|
|
7785
|
+
if (trimmed === "") delete draft.systemPrompt;
|
|
7786
|
+
else draft.systemPrompt = trimmed;
|
|
7787
|
+
});
|
|
7788
|
+
},
|
|
7789
|
+
async setSystemPromptEnabled(enabled) {
|
|
7790
|
+
await persistConfig((draft) => {
|
|
7791
|
+
draft.systemPromptEnabled = enabled;
|
|
7792
|
+
});
|
|
7793
|
+
},
|
|
7794
|
+
async loadSystemPromptFile(requestedPath) {
|
|
7795
|
+
const { readFile: readFile15 } = await import("fs/promises");
|
|
7796
|
+
const resolved = path15.resolve(options.cwd, requestedPath);
|
|
7797
|
+
return readFile15(resolved, "utf8");
|
|
7798
|
+
},
|
|
7799
|
+
getMaxTurnSteps: () => config.maxTurnSteps,
|
|
7800
|
+
async setMaxTurnSteps(steps) {
|
|
7801
|
+
await persistConfig((draft) => {
|
|
7802
|
+
draft.maxTurnSteps = steps;
|
|
7803
|
+
});
|
|
7804
|
+
},
|
|
7745
7805
|
getAccent: () => config.theme.accent,
|
|
7746
7806
|
async setAccent(value) {
|
|
7747
7807
|
await persistConfig((draft) => {
|
|
@@ -8322,7 +8382,7 @@ function validateKey(value) {
|
|
|
8322
8382
|
import { render } from "ink";
|
|
8323
8383
|
|
|
8324
8384
|
// src/ui/App.tsx
|
|
8325
|
-
import { Box as Box14, Text as Text13, useApp, useInput as
|
|
8385
|
+
import { Box as Box14, Text as Text13, useApp, useInput as useInput4, useStdout as useStdout2 } from "ink";
|
|
8326
8386
|
import { useCallback, useEffect as useEffect4, useMemo as useMemo6, useRef as useRef5, useState as useState8 } from "react";
|
|
8327
8387
|
|
|
8328
8388
|
// src/ui/terminal-size.ts
|
|
@@ -8508,6 +8568,8 @@ var COMMANDS = [
|
|
|
8508
8568
|
{ name: "mcp", args: "[add|list|delete|enable|disable]" },
|
|
8509
8569
|
{ name: "attach", args: "<path|clipboard|clear>" },
|
|
8510
8570
|
{ name: "memory", args: "[show|set <text>|clear]" },
|
|
8571
|
+
{ name: "systemp", args: "[set <text>|clear]", ...BUSY_SAFE },
|
|
8572
|
+
{ name: "steps", args: "[count]", ...BUSY_SAFE },
|
|
8511
8573
|
{ name: "compact" },
|
|
8512
8574
|
{ name: "update" },
|
|
8513
8575
|
{ name: "checker", ...BUSY_SAFE },
|
|
@@ -8881,6 +8943,17 @@ ${url}`,
|
|
|
8881
8943
|
memoryEmpty: "Project memory is empty.",
|
|
8882
8944
|
memoryClearAsk: "Clear project memory?",
|
|
8883
8945
|
memoryReplaceAsk: "Replace all project memory notes with this text?",
|
|
8946
|
+
systemPromptTitle: "System prompt addition",
|
|
8947
|
+
systemPromptUsage: "/systemp [show] \xB7 /systemp set <text> \xB7 /systemp clear",
|
|
8948
|
+
systemPromptEmpty: "No extra system prompt. Set one with /systemp set <text>.",
|
|
8949
|
+
systemPromptSet: "System prompt addition saved.",
|
|
8950
|
+
systemPromptCleared: "System prompt addition cleared.",
|
|
8951
|
+
systemPromptEnabled: "System prompt enabled.",
|
|
8952
|
+
systemPromptDisabled: "System prompt disabled (kept in config).",
|
|
8953
|
+
stepsCurrent: (n) => n === 0 ? "Model calls per turn: unlimited" : `Model calls per turn: ${n}`,
|
|
8954
|
+
stepsSet: (n) => `Model calls per turn set to ${n}`,
|
|
8955
|
+
stepsUnlimited: "Model calls per turn: unlimited (0). The turn budget still applies.",
|
|
8956
|
+
stepsInvalid: "Usage: /steps <0-1000> (0 = unlimited)",
|
|
8884
8957
|
promptDeleted: (name) => `Deleted prompt "${name}"`,
|
|
8885
8958
|
promptNotFound: (name) => `Prompt "${name}" not found.`,
|
|
8886
8959
|
promptsEmpty: "No saved prompts. Use /prompt save <name>.",
|
|
@@ -8923,6 +8996,8 @@ ${url}`,
|
|
|
8923
8996
|
theme: "change the accent colour",
|
|
8924
8997
|
lang: "change the interface language",
|
|
8925
8998
|
memory: "view, replace or clear project memory",
|
|
8999
|
+
systemp: "view, set, load from file, or toggle the extra system prompt",
|
|
9000
|
+
steps: "cap model calls per turn",
|
|
8926
9001
|
prompt: "insert or save a prompt",
|
|
8927
9002
|
"prompt save": "save the current or recent text as a prompt",
|
|
8928
9003
|
"prompt delete": "delete a saved prompt",
|
|
@@ -9118,6 +9193,17 @@ ${url}`,
|
|
|
9118
9193
|
memoryEmpty: "\u041F\u0430\u043C\u044F\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u043F\u0443\u0441\u0442\u0430.",
|
|
9119
9194
|
memoryClearAsk: "\u041E\u0447\u0438\u0441\u0442\u0438\u0442\u044C \u043F\u0430\u043C\u044F\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442\u0430?",
|
|
9120
9195
|
memoryReplaceAsk: "\u0417\u0430\u043C\u0435\u043D\u0438\u0442\u044C \u0432\u0441\u0435 \u0437\u0430\u043C\u0435\u0442\u043A\u0438 \u043F\u0430\u043C\u044F\u0442\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u044D\u0442\u0438\u043C \u0442\u0435\u043A\u0441\u0442\u043E\u043C?",
|
|
9196
|
+
systemPromptTitle: "\u0414\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043A \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043F\u0440\u043E\u043C\u043F\u0442\u0443",
|
|
9197
|
+
systemPromptUsage: "/systemp [show] \xB7 /systemp set <\u0442\u0435\u043A\u0441\u0442> \xB7 /systemp clear",
|
|
9198
|
+
systemPromptEmpty: "\u0414\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F \u043A \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043F\u0440\u043E\u043C\u043F\u0442\u0443 \u043D\u0435\u0442. \u0417\u0430\u0434\u0430\u0439 \u0447\u0435\u0440\u0435\u0437 /systemp set <\u0442\u0435\u043A\u0441\u0442>.",
|
|
9199
|
+
systemPromptSet: "\u0414\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043A \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043F\u0440\u043E\u043C\u043F\u0442\u0443 \u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043E.",
|
|
9200
|
+
systemPromptCleared: "\u0414\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043A \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043F\u0440\u043E\u043C\u043F\u0442\u0443 \u0443\u0434\u0430\u043B\u0435\u043D\u043E.",
|
|
9201
|
+
systemPromptEnabled: "\u0414\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043A \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043F\u0440\u043E\u043C\u043F\u0442\u0443 \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u043E.",
|
|
9202
|
+
systemPromptDisabled: "\u0414\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043A \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043F\u0440\u043E\u043C\u043F\u0442\u0443 \u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u043E (\u0441\u043E\u0445\u0440\u0430\u043D\u0435\u043D\u043E \u0432 \u043A\u043E\u043D\u0444\u0438\u0433\u0435).",
|
|
9203
|
+
stepsCurrent: (n) => n === 0 ? "\u0412\u044B\u0437\u043E\u0432\u043E\u0432 \u043C\u043E\u0434\u0435\u043B\u0438 \u0437\u0430 \u0445\u043E\u0434: \u0431\u0435\u0437 \u043B\u0438\u043C\u0438\u0442\u0430" : `\u0412\u044B\u0437\u043E\u0432\u043E\u0432 \u043C\u043E\u0434\u0435\u043B\u0438 \u0437\u0430 \u0445\u043E\u0434: ${n}`,
|
|
9204
|
+
stepsSet: (n) => `\u0412\u044B\u0437\u043E\u0432\u043E\u0432 \u043C\u043E\u0434\u0435\u043B\u0438 \u0437\u0430 \u0445\u043E\u0434 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043E: ${n}`,
|
|
9205
|
+
stepsUnlimited: "\u0412\u044B\u0437\u043E\u0432\u043E\u0432 \u043C\u043E\u0434\u0435\u043B\u0438 \u0437\u0430 \u0445\u043E\u0434: \u0431\u0435\u0437 \u043B\u0438\u043C\u0438\u0442\u0430 (0). \u0411\u044E\u0434\u0436\u0435\u0442 \u0442\u043E\u043A\u0435\u043D\u043E\u0432 \u0432\u0441\u0451 \u0435\u0449\u0451 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442.",
|
|
9206
|
+
stepsInvalid: "\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435: /steps <0-1000> (0 = \u0431\u0435\u0437 \u043B\u0438\u043C\u0438\u0442\u0430)",
|
|
9121
9207
|
promptDeleted: (name) => `\u041F\u0440\u043E\u043C\u0442 \xAB${name}\xBB \u0443\u0434\u0430\u043B\u0451\u043D`,
|
|
9122
9208
|
promptNotFound: (name) => `\u041F\u0440\u043E\u043C\u0442 \xAB${name}\xBB \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.`,
|
|
9123
9209
|
promptsEmpty: "\u0421\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0445 \u043F\u0440\u043E\u043C\u0442\u043E\u0432 \u043D\u0435\u0442. \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439 /prompt save <\u0438\u043C\u044F>.",
|
|
@@ -9160,6 +9246,8 @@ ${url}`,
|
|
|
9160
9246
|
theme: "\u0441\u043C\u0435\u043D\u0438\u0442\u044C \u0446\u0432\u0435\u0442 \u0430\u043A\u0446\u0435\u043D\u0442\u0430",
|
|
9161
9247
|
lang: "\u0441\u043C\u0435\u043D\u0438\u0442\u044C \u044F\u0437\u044B\u043A \u0438\u043D\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430",
|
|
9162
9248
|
memory: "\u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C, \u0437\u0430\u043C\u0435\u043D\u0438\u0442\u044C \u0438\u043B\u0438 \u043E\u0447\u0438\u0441\u0442\u0438\u0442\u044C \u043F\u0430\u043C\u044F\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442\u0430",
|
|
9249
|
+
systemp: "\u043F\u043E\u043A\u0430\u0437\u0430\u0442\u044C, \u0437\u0430\u0434\u0430\u0442\u044C, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0438\u0437 \u0444\u0430\u0439\u043B\u0430 \u0438\u043B\u0438 \u0432\u043A\u043B\u044E\u0447\u0438\u0442\u044C/\u0432\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0434\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043A \u0441\u0438\u0441\u0442\u0435\u043C\u043D\u043E\u043C\u0443 \u043F\u0440\u043E\u043C\u043F\u0442\u0443",
|
|
9250
|
+
steps: "\u043B\u0438\u043C\u0438\u0442 \u0432\u044B\u0437\u043E\u0432\u043E\u0432 \u043C\u043E\u0434\u0435\u043B\u0438 \u0437\u0430 \u0445\u043E\u0434",
|
|
9163
9251
|
prompt: "\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0438\u043B\u0438 \u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u043F\u0440\u043E\u043C\u0442",
|
|
9164
9252
|
skills: "\u0441\u043F\u0438\u0441\u043E\u043A \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D\u043D\u044B\u0445 \u0441\u043A\u0438\u043B\u043B\u043E\u0432",
|
|
9165
9253
|
"prompt delete": "\u0443\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u043E\u0445\u0440\u0430\u043D\u0451\u043D\u043D\u044B\u0439 \u043F\u0440\u043E\u043C\u0442",
|
|
@@ -9338,18 +9426,30 @@ function LanguagePicker({ onPick }) {
|
|
|
9338
9426
|
}
|
|
9339
9427
|
|
|
9340
9428
|
// src/ui/components/Onboarding.tsx
|
|
9341
|
-
import { Box as Box4, Text as Text4 } from "ink";
|
|
9429
|
+
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
9342
9430
|
import Spinner from "ink-spinner";
|
|
9343
9431
|
import TextInput from "ink-text-input";
|
|
9344
9432
|
import { useState as useState2 } from "react";
|
|
9345
9433
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
9346
|
-
function Onboarding({
|
|
9434
|
+
function Onboarding({
|
|
9435
|
+
onSubmit,
|
|
9436
|
+
onCancel
|
|
9437
|
+
}) {
|
|
9347
9438
|
const theme = useTheme();
|
|
9348
9439
|
const strings = useStrings();
|
|
9349
9440
|
const [step, setStep] = useState2("url");
|
|
9350
9441
|
const [url, setUrl] = useState2("");
|
|
9351
9442
|
const [key, setKey] = useState2("");
|
|
9352
9443
|
const [error, setError] = useState2("");
|
|
9444
|
+
useInput2((_input, inputKey) => {
|
|
9445
|
+
if (!inputKey.escape || step === "working") return;
|
|
9446
|
+
if (step === "key") {
|
|
9447
|
+
setError("");
|
|
9448
|
+
setStep("url");
|
|
9449
|
+
} else {
|
|
9450
|
+
onCancel?.();
|
|
9451
|
+
}
|
|
9452
|
+
});
|
|
9353
9453
|
const submitKey = async (value) => {
|
|
9354
9454
|
if (value.trim() === "") return;
|
|
9355
9455
|
setStep("working");
|
|
@@ -10355,13 +10455,12 @@ function ContextMeter({
|
|
|
10355
10455
|
}
|
|
10356
10456
|
|
|
10357
10457
|
// src/ui/components/SubagentChat.tsx
|
|
10358
|
-
import { Box as Box12, Text as Text12, useInput as
|
|
10458
|
+
import { Box as Box12, Text as Text12, useInput as useInput3 } from "ink";
|
|
10359
10459
|
import { useState as useState7 } from "react";
|
|
10360
10460
|
|
|
10361
10461
|
// src/ui/components/Transcript.tsx
|
|
10362
10462
|
import { Box as Box11, Static, Text as Text11 } from "ink";
|
|
10363
10463
|
import { memo as memo2, useEffect as useEffect3, useMemo as useMemo5, useRef as useRef4, useState as useState6 } from "react";
|
|
10364
|
-
import Spinner2 from "ink-spinner";
|
|
10365
10464
|
import stringWidth4 from "string-width";
|
|
10366
10465
|
|
|
10367
10466
|
// src/ui/markdown.tsx
|
|
@@ -11251,10 +11350,7 @@ function AssistantView({ bubble: source, maxRows }) {
|
|
|
11251
11350
|
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginTop: 1, children: [
|
|
11252
11351
|
frameThinking !== "" && /* @__PURE__ */ jsx11(Box11, { flexDirection: "column", maxHeight: thinkingBudget, overflowY: "hidden", children: /* @__PURE__ */ jsx11(Markdown, { dim: true, children: frameThinking }) }),
|
|
11253
11352
|
bubble.streaming ? /* @__PURE__ */ jsx11(Text11, { children: frameText }) : /* @__PURE__ */ jsx11(Markdown, { children: bubble.text }),
|
|
11254
|
-
bubble.streaming && bubble.text === "" && /* @__PURE__ */
|
|
11255
|
-
/* @__PURE__ */ jsx11(Spinner2, { type: "dots" }),
|
|
11256
|
-
" thinking"
|
|
11257
|
-
] })
|
|
11353
|
+
bubble.streaming && bubble.text === "" && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "thinking\u2026" })
|
|
11258
11354
|
] });
|
|
11259
11355
|
}
|
|
11260
11356
|
function clipTextToRows(text, maxRows, columns) {
|
|
@@ -11415,7 +11511,7 @@ function SubagentChat({
|
|
|
11415
11511
|
const strings = useStrings();
|
|
11416
11512
|
const [offset, setOffset] = useState7(0);
|
|
11417
11513
|
const total = bubble?.bubbles.length ?? 0;
|
|
11418
|
-
|
|
11514
|
+
useInput3((_input, key) => {
|
|
11419
11515
|
if (key.escape) onClose();
|
|
11420
11516
|
else if (key.upArrow) setOffset((value) => Math.min(Math.max(0, total - 1), value + 1));
|
|
11421
11517
|
else if (key.downArrow) setOffset((value) => Math.max(0, value - 1));
|
|
@@ -11464,25 +11560,44 @@ function SubagentChat({
|
|
|
11464
11560
|
|
|
11465
11561
|
// src/ui/components/TerminalViewport.tsx
|
|
11466
11562
|
import { Box as Box13 } from "ink";
|
|
11467
|
-
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
11468
|
-
var
|
|
11563
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
11564
|
+
var CHROME_ROWS = 16;
|
|
11469
11565
|
var MAX_LIVE_ROWS = 11;
|
|
11470
11566
|
var MIN_LIVE_ROWS = 4;
|
|
11471
|
-
|
|
11567
|
+
var BOTTOM_SLACK_ROWS = 3;
|
|
11568
|
+
function liveTranscriptRows(rows, chromeRows) {
|
|
11472
11569
|
if (!Number.isFinite(rows)) return MAX_LIVE_ROWS;
|
|
11473
|
-
|
|
11570
|
+
const chrome = chromeRows ?? CHROME_ROWS;
|
|
11571
|
+
const budget = Math.floor(rows) - chrome - BOTTOM_SLACK_ROWS - 1;
|
|
11572
|
+
return Math.max(MIN_LIVE_ROWS, Math.min(MAX_LIVE_ROWS, budget));
|
|
11474
11573
|
}
|
|
11475
11574
|
function TerminalViewport({ children, rows }) {
|
|
11476
11575
|
const { columns } = useTerminalSize();
|
|
11477
|
-
|
|
11576
|
+
const liveRows = liveTranscriptRows(rows);
|
|
11577
|
+
const items = Array.isArray(children) ? children : [children];
|
|
11578
|
+
const [transcript, ...chromeChildren] = items;
|
|
11579
|
+
return /* @__PURE__ */ jsxs13(
|
|
11478
11580
|
Box13,
|
|
11479
11581
|
{
|
|
11480
|
-
width: columns,
|
|
11582
|
+
width: columns - 1,
|
|
11481
11583
|
maxWidth: "100%",
|
|
11482
11584
|
flexDirection: "column",
|
|
11483
|
-
maxHeight:
|
|
11585
|
+
maxHeight: liveRows + CHROME_ROWS,
|
|
11484
11586
|
overflowY: "hidden",
|
|
11485
|
-
children
|
|
11587
|
+
children: [
|
|
11588
|
+
/* @__PURE__ */ jsx13(
|
|
11589
|
+
Box13,
|
|
11590
|
+
{
|
|
11591
|
+
flexDirection: "column",
|
|
11592
|
+
flexShrink: 1,
|
|
11593
|
+
minHeight: 0,
|
|
11594
|
+
maxHeight: liveRows,
|
|
11595
|
+
overflowY: "hidden",
|
|
11596
|
+
children: transcript
|
|
11597
|
+
}
|
|
11598
|
+
),
|
|
11599
|
+
/* @__PURE__ */ jsx13(Box13, { flexDirection: "column", flexShrink: 0, children: chromeChildren })
|
|
11600
|
+
]
|
|
11486
11601
|
}
|
|
11487
11602
|
);
|
|
11488
11603
|
}
|
|
@@ -11740,7 +11855,7 @@ function safeSummary(summarize, name, input) {
|
|
|
11740
11855
|
}
|
|
11741
11856
|
|
|
11742
11857
|
// src/ui/App.tsx
|
|
11743
|
-
import { jsx as jsx14, jsxs as
|
|
11858
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
11744
11859
|
var EFFORTS = ["auto", "low", "medium", "high", "xhigh", "max"];
|
|
11745
11860
|
var STREAM_FRAME_MS = 50;
|
|
11746
11861
|
var CUSTOM_ACCENT = "__custom__";
|
|
@@ -12022,6 +12137,7 @@ function App({
|
|
|
12022
12137
|
});
|
|
12023
12138
|
sessionStart.current = Date.now();
|
|
12024
12139
|
turns.current = 0;
|
|
12140
|
+
speedMeter.current = createSpeedMeter();
|
|
12025
12141
|
void runtime.persist([]).catch(
|
|
12026
12142
|
(error) => notice("error", error instanceof Error ? error.message : String(error))
|
|
12027
12143
|
);
|
|
@@ -12758,6 +12874,68 @@ ${strings.mcpAddUsage}`
|
|
|
12758
12874
|
notice("info", runtime.readMemory() || strings.memoryEmpty);
|
|
12759
12875
|
return;
|
|
12760
12876
|
}
|
|
12877
|
+
case "systemp": {
|
|
12878
|
+
const sub = rest[0]?.toLowerCase();
|
|
12879
|
+
if (sub === "set") {
|
|
12880
|
+
const text = rawRest.replace(/^\S+\s*/, "").trim();
|
|
12881
|
+
if (!text) {
|
|
12882
|
+
const typed = await promptInput(strings.systemPromptTitle);
|
|
12883
|
+
if (!typed || typed.trim() === "") return;
|
|
12884
|
+
await runtime.setSystemPrompt(typed);
|
|
12885
|
+
notice("info", strings.systemPromptSet);
|
|
12886
|
+
return;
|
|
12887
|
+
}
|
|
12888
|
+
await runtime.setSystemPrompt(text);
|
|
12889
|
+
notice("info", strings.systemPromptSet);
|
|
12890
|
+
return;
|
|
12891
|
+
}
|
|
12892
|
+
if (sub === "load") {
|
|
12893
|
+
const filePath = rawRest.replace(/^\S+\s*/, "").trim();
|
|
12894
|
+
if (!filePath) {
|
|
12895
|
+
notice("warn", strings.systemPromptUsage);
|
|
12896
|
+
return;
|
|
12897
|
+
}
|
|
12898
|
+
try {
|
|
12899
|
+
const text = await runtime.loadSystemPromptFile(filePath);
|
|
12900
|
+
await runtime.setSystemPrompt(text);
|
|
12901
|
+
notice("info", strings.systemPromptSet);
|
|
12902
|
+
} catch (error) {
|
|
12903
|
+
notice("error", error instanceof Error ? error.message : String(error));
|
|
12904
|
+
}
|
|
12905
|
+
return;
|
|
12906
|
+
}
|
|
12907
|
+
if (sub === "clear") {
|
|
12908
|
+
if (!runtime.getSystemPrompt()) {
|
|
12909
|
+
notice("info", strings.systemPromptEmpty);
|
|
12910
|
+
return;
|
|
12911
|
+
}
|
|
12912
|
+
await runtime.setSystemPrompt("");
|
|
12913
|
+
notice("info", strings.systemPromptCleared);
|
|
12914
|
+
return;
|
|
12915
|
+
}
|
|
12916
|
+
if (sub === "on") {
|
|
12917
|
+
await runtime.setSystemPromptEnabled(true);
|
|
12918
|
+
notice("info", strings.systemPromptEnabled);
|
|
12919
|
+
return;
|
|
12920
|
+
}
|
|
12921
|
+
if (sub === "off") {
|
|
12922
|
+
await runtime.setSystemPromptEnabled(false);
|
|
12923
|
+
notice("info", strings.systemPromptDisabled);
|
|
12924
|
+
return;
|
|
12925
|
+
}
|
|
12926
|
+
if (sub !== void 0 && sub !== "" && sub !== "show") {
|
|
12927
|
+
notice("warn", strings.systemPromptUsage);
|
|
12928
|
+
return;
|
|
12929
|
+
}
|
|
12930
|
+
const current = runtime.getSystemPrompt();
|
|
12931
|
+
if (!current) {
|
|
12932
|
+
notice("info", strings.systemPromptEmpty);
|
|
12933
|
+
return;
|
|
12934
|
+
}
|
|
12935
|
+
const enabled = runtime.isSystemPromptEnabled();
|
|
12936
|
+
notice("info", (enabled ? "" : "[disabled] ") + current);
|
|
12937
|
+
return;
|
|
12938
|
+
}
|
|
12761
12939
|
case "effort": {
|
|
12762
12940
|
notice("info", runtime.effortDescription(history.current));
|
|
12763
12941
|
const choice = EFFORTS.includes(rawRest) ? rawRest : await pick(
|
|
@@ -12770,6 +12948,21 @@ ${strings.mcpAddUsage}`
|
|
|
12770
12948
|
forceRender((n) => n + 1);
|
|
12771
12949
|
return;
|
|
12772
12950
|
}
|
|
12951
|
+
case "steps": {
|
|
12952
|
+
const current = runtime.getMaxTurnSteps();
|
|
12953
|
+
if (!rest[0]) {
|
|
12954
|
+
notice("info", strings.stepsCurrent(current));
|
|
12955
|
+
return;
|
|
12956
|
+
}
|
|
12957
|
+
const parsed = Number(rest[0]);
|
|
12958
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 1e3) {
|
|
12959
|
+
notice("warn", strings.stepsInvalid);
|
|
12960
|
+
return;
|
|
12961
|
+
}
|
|
12962
|
+
await runtime.setMaxTurnSteps(parsed);
|
|
12963
|
+
notice("info", parsed === 0 ? strings.stepsUnlimited : strings.stepsSet(parsed));
|
|
12964
|
+
return;
|
|
12965
|
+
}
|
|
12773
12966
|
case "budget": {
|
|
12774
12967
|
const current = runtime.getMaxTokensPerTurn();
|
|
12775
12968
|
if (rest[0]) {
|
|
@@ -13259,13 +13452,16 @@ ${strings.mcpAddUsage}`
|
|
|
13259
13452
|
notice("info", `${summary2}
|
|
13260
13453
|
${strings.configAt(runtime.configPath())}`);
|
|
13261
13454
|
return summary2;
|
|
13455
|
+
},
|
|
13456
|
+
onCancel: () => {
|
|
13457
|
+
if (!runtime.needsSetup()) setSetup(false);
|
|
13262
13458
|
}
|
|
13263
13459
|
}
|
|
13264
13460
|
)
|
|
13265
13461
|
);
|
|
13266
13462
|
}
|
|
13267
13463
|
return shell(
|
|
13268
|
-
/* @__PURE__ */
|
|
13464
|
+
/* @__PURE__ */ jsxs14(TerminalViewport, { rows, children: [
|
|
13269
13465
|
/* @__PURE__ */ jsx14(
|
|
13270
13466
|
Transcript,
|
|
13271
13467
|
{
|
|
@@ -13395,10 +13591,10 @@ function TextInputOverlay({
|
|
|
13395
13591
|
const submit = useCallback(() => {
|
|
13396
13592
|
onAnswer(value || null);
|
|
13397
13593
|
}, [value, onAnswer]);
|
|
13398
|
-
|
|
13594
|
+
useInput4((_input, key) => {
|
|
13399
13595
|
if (key.escape) onCancel();
|
|
13400
13596
|
});
|
|
13401
|
-
return /* @__PURE__ */
|
|
13597
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
13402
13598
|
/* @__PURE__ */ jsx14(Text13, { dimColor: true, children: title }),
|
|
13403
13599
|
/* @__PURE__ */ jsx14(
|
|
13404
13600
|
TextInput2,
|
|
@@ -13518,10 +13714,15 @@ function clearTerminal() {
|
|
|
13518
13714
|
if (process.stdout.isTTY) process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
13519
13715
|
}
|
|
13520
13716
|
var TUI_RENDER_OPTIONS = {
|
|
13521
|
-
//
|
|
13522
|
-
//
|
|
13523
|
-
|
|
13524
|
-
|
|
13717
|
+
// Incremental rendering is off: Ink's incremental diff races with its own
|
|
13718
|
+
// <Static> commits and leaves stale rows behind (the prompt frame appears
|
|
13719
|
+
// twice). Standard rendering clears the whole frame each time — a little
|
|
13720
|
+
// more work, but no stale lines.
|
|
13721
|
+
incrementalRendering: false,
|
|
13722
|
+
// Throttling defers writes; when a bubble closes into <Static> mid-stream,
|
|
13723
|
+
// the deferred frame and the static write race and leave stale rows behind.
|
|
13724
|
+
// Unthrottled renders cost a little CPU but keep every frame consistent.
|
|
13725
|
+
maxFps: 0
|
|
13525
13726
|
};
|
|
13526
13727
|
async function startTui(options) {
|
|
13527
13728
|
const { runtime, history, warnings, shutdown } = await boot({
|