pi-naming 0.6.0 → 0.7.1
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 +7 -1
- package/README.zh-CN.md +7 -1
- package/SKILL.md +1 -0
- package/config.example.json +1 -0
- package/locales/index.json +12 -4
- package/package.json +3 -3
- package/src/config-panel.ts +7 -0
- package/src/config.ts +6 -0
- package/src/index.ts +9 -5
- package/src/session-name.ts +18 -0
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Available through npm after publication. Run `/reload` after installation.
|
|
|
15
15
|
- **Automatic naming**: the first real user input in a new, unnamed session generates a title in the background and applies it to the allowed session, workspace and tab targets.
|
|
16
16
|
- **`/rename [name]`**: supply an explicit name, or omit it to generate one from user messages on the current branch. Uses the same targets and execution path as automatic naming.
|
|
17
17
|
- **`/config:naming`**: open the TUI settings panel (Pi's `SettingsList`); toggles switch in place, enums and numbers open a submenu, free text opens a prefilled input. Every change is saved and applied immediately, no `/reload`. Use `reset` to restore defaults.
|
|
18
|
-
-
|
|
18
|
+
- By default, model-based manual generation considers all user input on the current branch and names the main task. Explicit later corrections or goal changes take precedence; procedural follow-ups such as “continue”, “verify”, or “commit” should not overshadow the topic. Other branches, assistant replies and tool output are excluded. Automatic naming still attempts only once on the first input, not after every turn.
|
|
19
19
|
- Automatic results do not overwrite an existing name. Manual commands supersede pending requests; session switches and reloads discard old results and errors.
|
|
20
20
|
- Each target is independent. Unsupported, disabled, unidentified or failed terminal targets are reported without preventing session naming or other target updates. Non-UI modes receive Pi messages instead of silent failures.
|
|
21
21
|
|
|
@@ -33,6 +33,7 @@ File: `<pi-agent-dir>/extensions/pi-naming/config.json`; respects `PI_CODING_AGE
|
|
|
33
33
|
"tab": true
|
|
34
34
|
},
|
|
35
35
|
"title": {
|
|
36
|
+
"usePromptAsTitle": false,
|
|
36
37
|
"maxLength": 15,
|
|
37
38
|
"preferredLength": 10,
|
|
38
39
|
"language": "auto",
|
|
@@ -48,6 +49,7 @@ File: `<pi-agent-dir>/extensions/pi-naming/config.json`; respects `PI_CODING_AGE
|
|
|
48
49
|
|
|
49
50
|
| Title field | Default | Meaning |
|
|
50
51
|
| --- | --- | --- |
|
|
52
|
+
| `usePromptAsTitle` | `false` | Use a shortened literal first prompt and current directory name, without calling a model |
|
|
51
53
|
| `maxLength` | `15` | Maximum generated Unicode code points; longer output is truncated |
|
|
52
54
|
| `preferredLength` | `10` | Preferred length requested from the model; must not exceed the maximum |
|
|
53
55
|
| `language` | `"auto"` | Dominant message language, or a language such as `English` or `日本語` |
|
|
@@ -62,6 +64,10 @@ Lengths, timeout and output budget must be positive safe integers; timeout must
|
|
|
62
64
|
|
|
63
65
|
For longer English titles use `maxLength: 60`, `preferredLength: 40`, `language: "English"`. Model and authentication come from Pi's current selection; title language is independent of UI language.
|
|
64
66
|
|
|
67
|
+
Set `title.usePromptAsTitle: true` (or toggle **Use prompt as title** in `/config:naming`) for deterministic naming. Automatic naming uses the triggering prompt; `/rename` without a name uses the first nonempty user message on the current branch. The format is `directory: prompt`, for example `project: Fix the login timeout`. Whitespace is collapsed without stripping literal quotes, Markdown, or `title:` prefixes. The full title respects `maxLength` in Unicode code points: the directory uses at most half the available space, leaving room for the prompt; limits below 5 show only the prompt. Increase `maxLength` to preserve longer directory names and prompts.
|
|
68
|
+
|
|
69
|
+
This mode needs no model or credentials. Model-specific preferences (`preferredLength`, `language`, `instructions`, `timeoutMs`, `maxTokens`, `effort`) apply only to model-based naming. Explicit `/rename My title` still uses the supplied name verbatim. Changes in the panel take effect on the next naming operation.
|
|
70
|
+
|
|
65
71
|
## Standalone and composed use
|
|
66
72
|
|
|
67
73
|
- `pi-terminal-mux` is an automatically installed library dependency, not a separate extension to enable. It resolves terminal targets and executes renames, without generating titles.
|
package/README.zh-CN.md
CHANGED
|
@@ -15,7 +15,7 @@ pi install npm:pi-naming
|
|
|
15
15
|
- **首条消息自动命名**:新建且未命名的 session 收到首条真实用户输入后,后台生成标题,同步允许修改的 session、workspace 和 tab。
|
|
16
16
|
- **`/rename [名称]`**:显式指定名称,或省略名称、根据当前分支用户消息生成标题。与自动命名使用相同的目标配置和执行逻辑。
|
|
17
17
|
- **`/config:naming`**:打开 TUI 配置面板(Pi 自带 `SettingsList`);开关原地切换,枚举与数值回车开二级列表,自由文本回车开预填输入框。改一项立即保存并生效,不需要 `/reload`。输入 `reset` 恢复默认值。
|
|
18
|
-
-
|
|
18
|
+
- 默认的模型命名模式在手动生成时综合当前分支的全部用户输入,围绕主要任务命名;后续明确纠正或目标变更优先,“继续”“验证一下”“提交”等流程性跟进不应盖过主题。不会读取其他分支、assistant 回复或工具输出。自动命名仍仅在首条输入时尝试一次,不随每轮对话更新。
|
|
19
19
|
- 不覆盖已有名称的自动命名结果。手动命令优先于尚未完成的旧请求;会话切换或 reload 后丢弃旧结果和错误。
|
|
20
20
|
- 各目标独立执行。终端不支持、被禁用、缺少归属信息或改名失败均明确报告,不阻止 session 和其他可用目标改名。无交互 UI 时通过 Pi 消息报告。
|
|
21
21
|
|
|
@@ -33,6 +33,7 @@ pi install npm:pi-naming
|
|
|
33
33
|
"tab": true
|
|
34
34
|
},
|
|
35
35
|
"title": {
|
|
36
|
+
"usePromptAsTitle": false,
|
|
36
37
|
"maxLength": 15,
|
|
37
38
|
"preferredLength": 10,
|
|
38
39
|
"language": "auto",
|
|
@@ -48,6 +49,7 @@ pi install npm:pi-naming
|
|
|
48
49
|
|
|
49
50
|
| 标题字段 | 默认值 | 含义 |
|
|
50
51
|
| --- | --- | --- |
|
|
52
|
+
| `usePromptAsTitle` | `false` | 用首条提示词的字面文本和当前目录名生成标题,不调用模型 |
|
|
51
53
|
| `maxLength` | `15` | 生成标题最大 Unicode 码点数,超出时截断 |
|
|
52
54
|
| `preferredLength` | `10` | 提示模型优先采用的长度,不得超过最大长度 |
|
|
53
55
|
| `language` | `"auto"` | 跟随消息主要语言,或指定 `English`、`日本語` 等 |
|
|
@@ -62,6 +64,10 @@ pi install npm:pi-naming
|
|
|
62
64
|
|
|
63
65
|
例如较长英文标题:`maxLength: 60`、`preferredLength: 40`、`language: "English"`。模型和鉴权直接复用 Pi 当前选择;UI 语言与标题语言独立。
|
|
64
66
|
|
|
67
|
+
设置 `title.usePromptAsTitle: true`,或在 `/config:naming` 中打开「使用提示词命名」,即可使用确定性命名。自动命名使用触发它的提示词;不带名称的 `/rename` 使用当前分支首条非空用户消息。格式为 `目录名: 提示词`,例如 `project: 修复登录超时`。空白会合并为单个空格,保留字面引号、Markdown 和 `title:` 前缀。整个标题仍受 `maxLength` 的 Unicode 码点数限制:目录名最多占可用空间的一半,为提示词保留空间;上限小于 5 时只显示提示词。需要保留更长的目录名和提示词时可调大 `maxLength`。
|
|
68
|
+
|
|
69
|
+
此模式不需要模型或鉴权。模型相关偏好(`preferredLength`、`language`、`instructions`、`timeoutMs`、`maxTokens`、`effort`)仅作用于模型命名。显式 `/rename 自定义标题` 仍直接使用输入名称。面板改动在下一次命名时立即生效。
|
|
70
|
+
|
|
65
71
|
## 独立使用与组合
|
|
66
72
|
|
|
67
73
|
- `pi-terminal-mux` 是自动安装的库依赖,无需额外启用扩展;负责目标探测与终端执行,不负责生成标题。
|
package/SKILL.md
CHANGED
|
@@ -11,6 +11,7 @@ Use `/config:naming` to open the TUI settings panel (Pi's SettingsList); use `re
|
|
|
11
11
|
|
|
12
12
|
- `automaticNaming` / `manualNaming` 控制自动输入和 `/rename [名称]`,`targets` 直接分别控制 session/workspace/tab。Control automatic input and `/rename [name]`; `targets` directly selects session/workspace/tab.
|
|
13
13
|
- `title` 控制长度、语言、补充提示、超时、输出预算和思考档位(`maxTokens` 默认 2048、`effort` 默认 low,二者与 `maxLength` 相互独立);模型鉴权复用 Pi。Controls length, language, instructions, timeout, output budget and thinking effort (`maxTokens` default 2048, `effort` default low, both independent from `maxLength`); model authentication comes from Pi.
|
|
14
|
+
- `title.usePromptAsTitle` 默认 false;打开后用首条非空提示词与当前目录名生成 `目录名: 提示词`,自动和不带名称的 `/rename` 都不调用模型,也无需鉴权。整个标题受 `maxLength` 限制,目录最多占可用空间一半,上限小于 5 时仅保留提示词;其他模型偏好不适用。Defaults to false; enable it to use `directory: first prompt` without a model or credentials. The full title respects `maxLength`, reserving at least half the space for the prompt; limits below 5 omit the directory. Model-only preferences do not apply.
|
|
14
15
|
- 无终端也可命名 session;终端失败与跳过必须报告。普通会话明确目标路径不受旧 `PI_SUBAGENT_RENAME_*` 变量影响;关闭 target 即使变量为 `1` 也不执行。Session naming works without a terminal; report terminal failures and skips. The ordinary-session explicit-target path ignores legacy `PI_SUBAGENT_RENAME_*` variables; a disabled target never runs even when a variable is `1`.
|
|
15
16
|
- 子进程归属由启动方通过 mux 协议提供,不把 pane 扩大为共享 tab,不修改父 workspace。Launchers grant child targets through the mux protocol; never expand a pane to a shared tab or rename the parent workspace.
|
|
16
17
|
- 子代理需要显式配置 `subagentExtensions` 加载 naming。Child extension isolation requires explicitly loading naming in `subagentExtensions`.
|
package/config.example.json
CHANGED
package/locales/index.json
CHANGED
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"en-US": "Invalid configuration field: {field}. Check the field name, type and allowed range."
|
|
73
73
|
},
|
|
74
74
|
"renameDescription": {
|
|
75
|
-
"zh-CN": "统一命名 session
|
|
76
|
-
"en-US": "Name the session and allowed terminal targets; omit the name to
|
|
75
|
+
"zh-CN": "统一命名 session 与允许修改的终端目标;省略名称时按标题配置生成",
|
|
76
|
+
"en-US": "Name the session and allowed terminal targets; omit the name to generate a title using naming settings"
|
|
77
77
|
},
|
|
78
78
|
"namingManualDisabled": {
|
|
79
79
|
"zh-CN": "手动命名已关闭:用 /config:naming 打开「手动命名」后再试",
|
|
@@ -168,8 +168,8 @@
|
|
|
168
168
|
"en-US": "Manual /rename"
|
|
169
169
|
},
|
|
170
170
|
"panelDescManualNaming": {
|
|
171
|
-
"zh-CN": "允许用 /rename
|
|
172
|
-
"en-US": "Allow manual naming through /rename; omitting the name
|
|
171
|
+
"zh-CN": "允许用 /rename 手动命名;省略名称时按标题配置生成",
|
|
172
|
+
"en-US": "Allow manual naming through /rename; omitting the name generates a title using naming settings"
|
|
173
173
|
},
|
|
174
174
|
"panelLabelSessionTarget": {
|
|
175
175
|
"zh-CN": "命名 session",
|
|
@@ -258,5 +258,13 @@
|
|
|
258
258
|
"panelValueUnset": {
|
|
259
259
|
"zh-CN": "未设置",
|
|
260
260
|
"en-US": "not set"
|
|
261
|
+
},
|
|
262
|
+
"panelLabelUsePromptAsTitle": {
|
|
263
|
+
"zh-CN": "使用提示词命名",
|
|
264
|
+
"en-US": "Use prompt as title"
|
|
265
|
+
},
|
|
266
|
+
"panelDescUsePromptAsTitle": {
|
|
267
|
+
"zh-CN": "用首条提示词和当前目录名生成标题,不调用模型",
|
|
268
|
+
"en-US": "Use the first prompt and current directory name without a model request"
|
|
261
269
|
}
|
|
262
270
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-naming",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "Configurable Pi session naming and manual terminal workspace/tab renaming",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"pi-extensions-i18n": "^0.9.0",
|
|
61
61
|
"pi-model-request": "^0.1.1",
|
|
62
|
-
"pi-terminal-mux": "^0.6.
|
|
62
|
+
"pi-terminal-mux": "^0.6.8"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@earendil-works/pi-ai": ">=0.80.0",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@earendil-works/pi-tui": "0.85.1",
|
|
73
73
|
"@types/node": "24.12.4",
|
|
74
74
|
"pi-model-request": "^0.1.1",
|
|
75
|
-
"pi-terminal-mux": "^0.6.
|
|
75
|
+
"pi-terminal-mux": "^0.6.8",
|
|
76
76
|
"tsx": "4.23.1",
|
|
77
77
|
"typescript": "5.9.3"
|
|
78
78
|
}
|
package/src/config-panel.ts
CHANGED
|
@@ -33,6 +33,7 @@ export const PANEL_FIELD = {
|
|
|
33
33
|
sessionTarget: "targets.session",
|
|
34
34
|
workspaceTarget: "targets.workspace",
|
|
35
35
|
tabTarget: "targets.tab",
|
|
36
|
+
usePromptAsTitle: "title.usePromptAsTitle",
|
|
36
37
|
maxLength: "title.maxLength",
|
|
37
38
|
preferredLength: "title.preferredLength",
|
|
38
39
|
language: "title.language",
|
|
@@ -81,6 +82,7 @@ const PANEL_FIELDS: readonly PanelField[] = [
|
|
|
81
82
|
{ id: PANEL_FIELD.sessionTarget, kind: "toggle", labelKey: "panelLabelSessionTarget", descriptionKey: "panelDescSessionTarget" },
|
|
82
83
|
{ id: PANEL_FIELD.workspaceTarget, kind: "toggle", labelKey: "panelLabelWorkspaceTarget", descriptionKey: "panelDescWorkspaceTarget" },
|
|
83
84
|
{ id: PANEL_FIELD.tabTarget, kind: "toggle", labelKey: "panelLabelTabTarget", descriptionKey: "panelDescTabTarget" },
|
|
85
|
+
{ id: PANEL_FIELD.usePromptAsTitle, kind: "toggle", labelKey: "panelLabelUsePromptAsTitle", descriptionKey: "panelDescUsePromptAsTitle" },
|
|
84
86
|
{ id: PANEL_FIELD.maxLength, kind: "choice", labelKey: "panelLabelMaxLength", descriptionKey: "panelDescMaxLength" },
|
|
85
87
|
{ id: PANEL_FIELD.preferredLength, kind: "choice", labelKey: "panelLabelPreferredLength", descriptionKey: "panelDescPreferredLength" },
|
|
86
88
|
{ id: PANEL_FIELD.language, kind: "choice", labelKey: "panelLabelLanguage", descriptionKey: "panelDescLanguage" },
|
|
@@ -137,6 +139,7 @@ function fieldOptions(id: PanelFieldId, config: NamingConfig): PanelOption[] {
|
|
|
137
139
|
case PANEL_FIELD.sessionTarget:
|
|
138
140
|
case PANEL_FIELD.workspaceTarget:
|
|
139
141
|
case PANEL_FIELD.tabTarget:
|
|
142
|
+
case PANEL_FIELD.usePromptAsTitle:
|
|
140
143
|
return toggleOptions();
|
|
141
144
|
case PANEL_FIELD.maxLength:
|
|
142
145
|
return numberOptions(MAX_LENGTH_PRESETS);
|
|
@@ -181,6 +184,8 @@ function readField(config: NamingConfig, id: PanelFieldId): string {
|
|
|
181
184
|
return config.targets.workspace ? TOGGLE_ON : TOGGLE_OFF;
|
|
182
185
|
case PANEL_FIELD.tabTarget:
|
|
183
186
|
return config.targets.tab ? TOGGLE_ON : TOGGLE_OFF;
|
|
187
|
+
case PANEL_FIELD.usePromptAsTitle:
|
|
188
|
+
return config.title.usePromptAsTitle ? TOGGLE_ON : TOGGLE_OFF;
|
|
184
189
|
case PANEL_FIELD.maxLength:
|
|
185
190
|
return String(config.title.maxLength);
|
|
186
191
|
case PANEL_FIELD.preferredLength:
|
|
@@ -212,6 +217,8 @@ function writeField(config: NamingConfig, id: PanelFieldId, value: string): Nami
|
|
|
212
217
|
return { ...config, targets: { ...config.targets, workspace: value === TOGGLE_ON } };
|
|
213
218
|
case PANEL_FIELD.tabTarget:
|
|
214
219
|
return { ...config, targets: { ...config.targets, tab: value === TOGGLE_ON } };
|
|
220
|
+
case PANEL_FIELD.usePromptAsTitle:
|
|
221
|
+
return { ...config, title: { ...title, usePromptAsTitle: value === TOGGLE_ON } };
|
|
215
222
|
case PANEL_FIELD.maxLength:
|
|
216
223
|
return { ...config, title: { ...title, maxLength: Number(value) } };
|
|
217
224
|
case PANEL_FIELD.preferredLength:
|
package/src/config.ts
CHANGED
|
@@ -29,6 +29,7 @@ const NAMING_SWITCHES = ["automaticNaming", "manualNaming"] as const;
|
|
|
29
29
|
const TARGET_KEYS = ["session", "workspace", "tab"] as const;
|
|
30
30
|
|
|
31
31
|
export interface TitleConfig {
|
|
32
|
+
usePromptAsTitle: boolean;
|
|
32
33
|
maxLength: number;
|
|
33
34
|
preferredLength: number;
|
|
34
35
|
language: string;
|
|
@@ -39,6 +40,7 @@ export interface TitleConfig {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export const DEFAULT_TITLE_CONFIG: Readonly<TitleConfig> = Object.freeze({
|
|
43
|
+
usePromptAsTitle: false,
|
|
42
44
|
maxLength: 15,
|
|
43
45
|
preferredLength: 10,
|
|
44
46
|
language: "auto",
|
|
@@ -94,6 +96,10 @@ export function parseConfig(value: unknown): NamingConfig {
|
|
|
94
96
|
if (!Object.hasOwn(DEFAULT_TITLE_CONFIG, key)) invalid(`title.${key}`);
|
|
95
97
|
}
|
|
96
98
|
const title: TitleConfig = { ...DEFAULT_TITLE_CONFIG };
|
|
99
|
+
if (titleRaw.usePromptAsTitle !== undefined) {
|
|
100
|
+
if (typeof titleRaw.usePromptAsTitle !== "boolean") invalid("title.usePromptAsTitle");
|
|
101
|
+
title.usePromptAsTitle = titleRaw.usePromptAsTitle;
|
|
102
|
+
}
|
|
97
103
|
for (const key of ["maxLength", "preferredLength", "timeoutMs", "maxTokens"] as const) {
|
|
98
104
|
if (titleRaw[key] !== undefined) title[key] = positiveInteger(titleRaw[key], `title.${key}`);
|
|
99
105
|
}
|
package/src/index.ts
CHANGED
|
@@ -11,7 +11,7 @@ const NOTICE_TAG = "naming";
|
|
|
11
11
|
const NOTICE_COLOR: NoticeColor = NOTICE_TAG_COLOR;
|
|
12
12
|
/** 本扩展的提示来源。 */
|
|
13
13
|
const NOTICE_SOURCE: NoticeSource = { tag: NOTICE_TAG, color: NOTICE_COLOR };
|
|
14
|
-
import { getCurrentSessionUserMessages, requestSessionNameWithTimeout, type SessionNameRequester } from "./session-name.ts";
|
|
14
|
+
import { buildPromptSessionName, getCurrentSessionUserMessages, requestSessionNameWithTimeout, type SessionNameRequester } from "./session-name.ts";
|
|
15
15
|
|
|
16
16
|
const RENAME_COMMAND = "rename";
|
|
17
17
|
const CONFIG_COMMAND_ALIASES = ["config:naming", "naming-config", "pi-naming-config"] as const;
|
|
@@ -168,10 +168,14 @@ export async function registerNaming(
|
|
|
168
168
|
let label = automatic ? "" : args.trim();
|
|
169
169
|
if (!label) {
|
|
170
170
|
try {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
171
|
+
const userMessages = automatic ? [args] : getCurrentSessionUserMessages(ctx);
|
|
172
|
+
const title = current().title;
|
|
173
|
+
label = title.usePromptAsTitle
|
|
174
|
+
? buildPromptSessionName(userMessages, ctx.cwd, title.maxLength)
|
|
175
|
+
: await requestSessionNameWithTimeout({
|
|
176
|
+
userMessages,
|
|
177
|
+
ctx, requestName, title,
|
|
178
|
+
});
|
|
175
179
|
} catch (error) {
|
|
176
180
|
if (isCurrent()) report(pi, ctx, { message: i18n.t("namingFailed", { error: errorMessage(error) }), level: "error" });
|
|
177
181
|
return;
|
package/src/session-name.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
SessionEntry,
|
|
5
5
|
} from "@earendil-works/pi-coding-agent";
|
|
6
6
|
import { createModelRequester } from "pi-model-request";
|
|
7
|
+
import { basename } from "node:path";
|
|
7
8
|
import { i18n } from "./i18n.ts";
|
|
8
9
|
import { DEFAULT_TITLE_CONFIG, type TitleConfig } from "./config.ts";
|
|
9
10
|
|
|
@@ -131,6 +132,23 @@ export function normalizeSessionName(raw: string, maxLength = DEFAULT_TITLE_CONF
|
|
|
131
132
|
return Array.from(name).slice(0, maxLength).join("").trim();
|
|
132
133
|
}
|
|
133
134
|
|
|
135
|
+
/** 用首条非空提示词和目录名生成标题,保留字面文本,不做模型响应格式清理。 */
|
|
136
|
+
export function buildPromptSessionName(
|
|
137
|
+
userMessages: readonly string[],
|
|
138
|
+
cwd: string,
|
|
139
|
+
maxLength = DEFAULT_TITLE_CONFIG.maxLength,
|
|
140
|
+
): string {
|
|
141
|
+
const singleLine = (value: string): string => value.replace(/[\u0000-\u001f\u007f-\u009f]/g, " ").replace(/\s+/g, " ").trim();
|
|
142
|
+
const prompt = userMessages.map(singleLine).find(Boolean);
|
|
143
|
+
if (!prompt) throw new Error(i18n.t("sessionNameNoMessages"));
|
|
144
|
+
const promptPoints = Array.from(prompt);
|
|
145
|
+
const directory = Array.from(singleLine(basename(cwd) || cwd));
|
|
146
|
+
// 至少给提示词留一半空间;极短上限只显示提示词,避免目录前缀挤掉整个主题。
|
|
147
|
+
if (directory.length === 0 || maxLength < 5) return promptPoints.slice(0, maxLength).join("").trim();
|
|
148
|
+
const directoryLength = Math.min(directory.length, Math.floor((maxLength - 2) / 2));
|
|
149
|
+
return `${directory.slice(0, directoryLength).join("")}: ${promptPoints.slice(0, maxLength - directoryLength - 2).join("")}`.trim();
|
|
150
|
+
}
|
|
151
|
+
|
|
134
152
|
/** 调用当前 session 模型生成名称,并把鉴权、空响应和模型错误显式抛出。 */
|
|
135
153
|
export async function requestSessionName({
|
|
136
154
|
userMessages,
|