u1s1-cli 0.7.2 → 0.8.0

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.
@@ -45,6 +45,21 @@ export function ensureDefaultSettings() {
45
45
  settings["hideThinkingBlock"] = true;
46
46
  changed = true;
47
47
  }
48
+ // 启动时是否显示品牌横幅(logo + 版本号/目录/提示)
49
+ if (!("showStartupBanner" in settings)) {
50
+ settings["showStartupBanner"] = true;
51
+ changed = true;
52
+ }
53
+ // 静默启动:不打印 [Context]/[Skills]/[Extensions] 等资源加载信息
54
+ if (!("quietStartup" in settings)) {
55
+ settings["quietStartup"] = true;
56
+ changed = true;
57
+ }
58
+ // 启动时自动检查并更新新版
59
+ if (!("autoUpdate" in settings)) {
60
+ settings["autoUpdate"] = true;
61
+ changed = true;
62
+ }
48
63
  // ≤0.4.0 shipped branded themes and forced them as default; the files are
49
64
  // gone now, so a settings.json still pointing at them must fall back to
50
65
  // pi's default theme.
package/dist/config.js CHANGED
@@ -38,7 +38,7 @@ export const MODELS = [
38
38
  aliases: ["deepseek", "flash", "v4-flash"],
39
39
  reasoning: false,
40
40
  contextWindow: 1_048_576,
41
- maxTokens: 65_536,
41
+ maxTokens: 384_000,
42
42
  cost: { input: 0.14, output: 0.28, cacheRead: 0, cacheWrite: 0 },
43
43
  note: "默认 · 便宜大碗,日常写代码首选",
44
44
  },
@@ -67,7 +67,7 @@ export const u1s1Dir = join(homedir(), ".u1s1");
67
67
  const configFile = join(u1s1Dir, "config.json");
68
68
  /** pi keeps auth/models/settings/sessions under this dir — isolated from any real pi install. */
69
69
  export const agentDir = join(u1s1Dir, "agent");
70
- const agentSettingsFile = join(agentDir, "settings.json");
70
+ export const agentSettingsFile = join(agentDir, "settings.json");
71
71
  function readJsonFile(path) {
72
72
  if (!existsSync(path))
73
73
  return undefined;
@@ -78,6 +78,10 @@ function readJsonFile(path) {
78
78
  return undefined;
79
79
  }
80
80
  }
81
+ /** Read u1s1 agent settings (settings.json). Returns empty object if missing or invalid. */
82
+ export function readSettings() {
83
+ return (readJsonFile(agentSettingsFile) ?? {});
84
+ }
81
85
  /** Model last chosen in-session via /model (pi writes this). */
82
86
  export function readAgentDefaultModel() {
83
87
  const settings = readJsonFile(agentSettingsFile);
package/dist/index.js CHANGED
@@ -4,11 +4,70 @@ import { writeFileSync } from "node:fs";
4
4
  import { createRequire } from "node:module";
5
5
  import { cleanupBrandThemes, ensureBrandPrompt, ensureDefaultSettings, ensureProviderModels, } from "./agent-setup.js";
6
6
  import { printConsoleBanner } from "./brand.js";
7
- import { agentDir, apiModelToDef, loadConfig, MODELS, persistPreferredModel, PROVIDER_ID, resolvePreferredModel, setModelsFromApi, } from "./config.js";
7
+ import { agentDir, apiModelToDef, loadConfig, MODELS, persistPreferredModel, PROVIDER_ID, readSettings, resolvePreferredModel, setModelsFromApi, } from "./config.js";
8
8
  import { applyBrandUi } from "./style.js";
9
9
  import { fetchModels } from "./api.js";
10
10
  const require = createRequire(import.meta.url);
11
11
  const VERSION = require("../package.json").version;
12
+ const PACKAGE_NAME = "u1s1-cli";
13
+ /**
14
+ * 启动时自动检查 npm 最新版,发现更新就静默安装。
15
+ * 不阻塞启动流程,失败也不报错(留到手动 `u1s1 update`)。
16
+ */
17
+ async function checkAndAutoUpdate() {
18
+ const settings = readSettings();
19
+ if (settings.autoUpdate === false)
20
+ return;
21
+ let latest;
22
+ try {
23
+ const url = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
24
+ const res = await fetch(url, {
25
+ headers: { Accept: "application/json" },
26
+ signal: AbortSignal.timeout(5_000),
27
+ });
28
+ if (res.ok) {
29
+ const body = (await res.json());
30
+ latest = body.version;
31
+ }
32
+ }
33
+ catch {
34
+ return; // 网络不可用,静默跳过
35
+ }
36
+ if (!latest)
37
+ return;
38
+ const pa = VERSION.split(".").map(Number);
39
+ const pb = latest.split(".").map(Number);
40
+ let newer = false;
41
+ for (let i = 0; i < 3; i++) {
42
+ const diff = (pb[i] ?? 0) - (pa[i] ?? 0);
43
+ if (diff > 0) {
44
+ newer = true;
45
+ break;
46
+ }
47
+ if (diff < 0)
48
+ break;
49
+ }
50
+ if (!newer)
51
+ return;
52
+ // 检测包管理器
53
+ const userAgent = process.env.npm_config_user_agent ?? "";
54
+ const pm = userAgent.startsWith("pnpm") ? "pnpm"
55
+ : userAgent.startsWith("yarn") ? "yarn"
56
+ : userAgent.startsWith("bun") ? "bun"
57
+ : "npm";
58
+ const installCmd = pm === "npm"
59
+ ? `npm install -g ${PACKAGE_NAME}@latest`
60
+ : `${pm} add -g ${PACKAGE_NAME}@latest`;
61
+ try {
62
+ // 用同步 execSync 确保安装完成后再进交互
63
+ const { execSync } = await import("node:child_process");
64
+ execSync(installCmd, { stdio: "pipe", timeout: 60_000 });
65
+ console.log(` ✨ 已自动更新到 v${latest},下次启动生效`);
66
+ }
67
+ catch {
68
+ // 自动更新失败不阻塞,用户可手动 `u1s1 update`
69
+ }
70
+ }
12
71
  /**
13
72
  * tmux 默认不转发键盘修饰键,会把 Shift+Enter 当成普通回车发出去,消息没写完就被发送。
14
73
  * 只开 extended-keys 不够:默认 terminal-features 里 xterm* 没有 extkeys,tmux 根本不会
@@ -105,6 +164,17 @@ async function runAgent(cfg, args) {
105
164
  ctx.shutdown();
106
165
  },
107
166
  });
167
+ // /clear: 清空当前对话上下文,开始新会话
168
+ pi.registerCommand("clear", {
169
+ description: "清除当前对话上下文,开始新会话",
170
+ handler: async (_args, ctx) => {
171
+ await ctx.newSession({
172
+ withSession: async (ctx) => {
173
+ ctx.ui.notify("🗑️ 上下文已清除", "info");
174
+ },
175
+ });
176
+ },
177
+ });
108
178
  pi.registerProvider(PROVIDER_ID, {
109
179
  name: "u1s1",
110
180
  baseUrl: cfg.baseUrl,
@@ -210,6 +280,8 @@ async function run() {
210
280
  }
211
281
  const { ensureAuth } = await import("./login.js");
212
282
  const cfg = await ensureAuth();
283
+ // 在后台检查更新(非阻塞,不影响启动速度)
284
+ void checkAndAutoUpdate();
213
285
  await runAgent(cfg, args);
214
286
  }
215
287
  run().catch((e) => {
package/dist/style.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { basename } from "node:path";
2
2
  import { truncateToWidth } from "@earendil-works/pi-tui";
3
+ import { readSettings } from "./config.js";
3
4
  import { renderBrandHeader } from "./brand.js";
4
5
  /**
5
6
  * Brand chrome is just the startup hero + window title; everything else
@@ -9,13 +10,17 @@ export function applyBrandUi(pi, version) {
9
10
  pi.on("session_start", async (_event, ctx) => {
10
11
  if (ctx.mode !== "tui")
11
12
  return;
12
- ctx.ui.setHeader((_tui, theme) => ({
13
- render(width) {
14
- // pi-tui crashes on lines wider than the terminal, so truncate defensively.
15
- return renderBrandHeader(theme, version, process.cwd(), width).map((line) => truncateToWidth(line, width));
16
- },
17
- invalidate() { },
18
- }));
13
+ // 检查设置:关掉就不显示启动横幅
14
+ const settings = readSettings();
15
+ if (settings.showStartupBanner !== false) {
16
+ ctx.ui.setHeader((_tui, theme) => ({
17
+ render(width) {
18
+ // pi-tui crashes on lines wider than the terminal, so truncate defensively.
19
+ return renderBrandHeader(theme, version, process.cwd(), width).map((line) => truncateToWidth(line, width));
20
+ },
21
+ invalidate() { },
22
+ }));
23
+ }
19
24
  ctx.ui.setTitle(`u1s1 — ${basename(process.cwd())}`);
20
25
  });
21
26
  }
package/dist/update.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { execSync } from "node:child_process";
2
2
  import { createRequire } from "node:module";
3
3
  const require = createRequire(import.meta.url);
4
- const VERSION = require("../package.json").version;
5
- const PACKAGE_NAME = "u1s1-cli";
4
+ export const VERSION = require("../package.json").version;
5
+ export const PACKAGE_NAME = "u1s1-cli";
6
6
  /** Detect the package manager that installed u1s1. */
7
- function detectPackageManager() {
7
+ export function detectPackageManager() {
8
8
  // Check common global install locations for clues
9
9
  const userAgent = process.env.npm_config_user_agent ?? "";
10
10
  if (userAgent.startsWith("pnpm"))
@@ -16,7 +16,7 @@ function detectPackageManager() {
16
16
  return "npm";
17
17
  }
18
18
  /** Fetch the latest published version from npm registry. */
19
- async function getLatestVersion() {
19
+ export async function getLatestVersion() {
20
20
  const url = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
21
21
  try {
22
22
  const res = await fetch(url, {
@@ -32,7 +32,7 @@ async function getLatestVersion() {
32
32
  return undefined;
33
33
  }
34
34
  }
35
- function compareVersions(a, b) {
35
+ export function compareVersions(a, b) {
36
36
  const pa = a.split(".").map(Number);
37
37
  const pb = b.split(".").map(Number);
38
38
  for (let i = 0; i < 3; i++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "u1s1-cli",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "u1s1 — 有一说一,最省心的 AI 编程搭子。终端里用中文说需求,AI 帮你读文件、改代码、跑命令。",
5
5
  "type": "module",
6
6
  "bin": {