flavor-code 1.3.15 → 1.3.17

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 CHANGED
@@ -271,7 +271,7 @@ Project runtime data lives under `.flavor/`:
271
271
  ├── sessions/ # Session timelines
272
272
  │ └── *.events.jsonl # Crash-consistent execution journals
273
273
  ├── session-assets/ # Image attachments
274
- ├── session-trees/ # Session branches
274
+ ├── session-trees/ # Explicit /checkpoint session branches
275
275
  ├── checkpoints/ # Workspace snapshots
276
276
  ├── memory/ # Long-term memory
277
277
  ├── traces/ # Optional execution traces
package/README.zh-CN.md CHANGED
@@ -271,7 +271,7 @@ Skill 是带有 YAML 头信息的 `SKILL.md`,放在 `.flavor/skills/<name>/`
271
271
  ├── sessions/ # 会话时间线
272
272
  │ └── *.events.jsonl # 崩溃一致执行事件日志
273
273
  ├── session-assets/ # 图片附件
274
- ├── session-trees/ # 会话分支
274
+ ├── session-trees/ # 手动 /checkpoint 创建的会话分支
275
275
  ├── checkpoints/ # 工作区快照
276
276
  ├── memory/ # 长期记忆
277
277
  ├── traces/ # 可选执行 trace
@@ -4,7 +4,16 @@ import type { HookBus } from "../hooks/bus.js";
4
4
  import type { ModelRegistry } from "../models/registry.js";
5
5
  import { type ModelMessage, type ModelTool } from "../models/types.js";
6
6
  import type { ToolRuntime } from "../tools/runtime.js";
7
- import type { AgentEvent, AgentRunRequest } from "./types.js";
7
+ import type { AgentError, AgentEvent, AgentRunRequest } from "./types.js";
8
+ /**
9
+ * Stop a turn before the V8 heap reaches its hard limit. A retained-memory
10
+ * leak otherwise ends in a native OOM crash with no recovery; tripping this
11
+ * watermark saves the session and lets the launcher relaunch on a fresh heap.
12
+ * 0.8 keeps headroom for compaction payloads and the GC death spiral that
13
+ * starts near ~0.95.
14
+ */
15
+ export declare const MEMORY_PRESSURE_HEAP_RATIO = 0.8;
16
+ export declare function memoryPressureError(heapUsed: number, heapLimit: number): AgentError | undefined;
8
17
  export interface AgentLoopOptions {
9
18
  registry: ModelRegistry;
10
19
  modelId: string;
@@ -15,7 +15,7 @@ export interface AgentRunRequest {
15
15
  /** Messages supplied while a tool batch is running, injected before the next model call. */
16
16
  getSteeringMessages?(): readonly string[];
17
17
  }
18
- export type AgentErrorCode = ProviderErrorCode | "iteration_limit" | "incomplete_stream" | "empty_response";
18
+ export type AgentErrorCode = ProviderErrorCode | "iteration_limit" | "incomplete_stream" | "empty_response" | "memory_pressure";
19
19
  export interface AgentError {
20
20
  code: AgentErrorCode;
21
21
  message: string;
@@ -18,8 +18,9 @@ import {
18
18
  thinkingWindow,
19
19
  transcriptReducer,
20
20
  withTimeout
21
- } from "./chunk-WB4IJXFT.js";
22
- import "./chunk-JFKRX2KG.js";
21
+ } from "./chunk-BKOOYSGH.js";
22
+ import "./chunk-CIVPKHF4.js";
23
+ import "./chunk-HJOCNKPN.js";
23
24
  import {
24
25
  Box_default,
25
26
  ClockContext,
@@ -29,14 +30,16 @@ import {
29
30
  TerminalSizeContext,
30
31
  TerminalWriteContext,
31
32
  Text,
33
+ gt,
32
34
  instances_default,
35
+ isValidVersion,
33
36
  osc,
34
37
  shiftAnchor,
35
38
  stripAnsi,
36
39
  useStdout,
37
40
  use_app_default,
38
41
  use_input_default
39
- } from "./chunk-F2HMO5Q2.js";
42
+ } from "./chunk-36UKDXPF.js";
40
43
  import {
41
44
  execFileNoThrow
42
45
  } from "./chunk-RQTYHUMK.js";
@@ -1307,6 +1310,41 @@ function comparePaths(left, right) {
1307
1310
  return left.localeCompare(right, "en");
1308
1311
  }
1309
1312
 
1313
+ // src/update/check.ts
1314
+ var NPM_PACKAGE_NAME = "flavor-code";
1315
+ var REGISTRY_LATEST_URL = `https://registry.npmjs.org/${NPM_PACKAGE_NAME}/latest`;
1316
+ var DEFAULT_TIMEOUT_MS = 3e3;
1317
+ function findNewerVersion(current, latest) {
1318
+ if (!isValidVersion(current) || !isValidVersion(latest)) return void 0;
1319
+ return gt(latest, current) ? latest : void 0;
1320
+ }
1321
+ async function fetchLatestVersion(options = {}) {
1322
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1323
+ const fetchImpl = options.fetchImpl ?? ((url, init) => fetch(url, init));
1324
+ let timer;
1325
+ const timeout = new Promise((resolve2) => {
1326
+ timer = setTimeout(() => resolve2(void 0), timeoutMs);
1327
+ timer.unref?.();
1328
+ });
1329
+ try {
1330
+ const response = await Promise.race([
1331
+ fetchImpl(REGISTRY_LATEST_URL, { signal: AbortSignal.timeout(timeoutMs) }),
1332
+ timeout
1333
+ ]);
1334
+ if (response === void 0 || !response.ok) return void 0;
1335
+ const body = await Promise.race([response.json(), timeout]);
1336
+ return typeof body?.version === "string" ? body.version : void 0;
1337
+ } catch {
1338
+ return void 0;
1339
+ } finally {
1340
+ if (timer !== void 0) clearTimeout(timer);
1341
+ }
1342
+ }
1343
+ async function checkForUpdate(current, options = {}) {
1344
+ const latest = await fetchLatestVersion(options);
1345
+ return latest === void 0 ? void 0 : findNewerVersion(current, latest);
1346
+ }
1347
+
1310
1348
  // src/ui/welcome.tsx
1311
1349
  import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1312
1350
  var WIDE_WELCOME_COLUMNS = 72;
@@ -1316,8 +1354,25 @@ var FLAVOR_WORDMARK = [
1316
1354
  "\u251C\u2524 \u2502 \u251C\u2500\u2524\u2514\u2510\u250C\u2518\u2502 \u2502\u251C\u252C\u2518",
1317
1355
  "\u2514 \u2534\u2500\u2518\u2534 \u2534 \u2514\u2518 \u2514\u2500\u2518\u2534\u2514\u2500"
1318
1356
  ].join("\n");
1319
- function WelcomeCard({ model, serviceName, workspaceName, columns }) {
1357
+ function WelcomeCard({
1358
+ model,
1359
+ serviceName,
1360
+ workspaceName,
1361
+ updateTo,
1362
+ columns
1363
+ }) {
1320
1364
  const wide = Math.max(1, Math.floor(columns)) >= WIDE_WELCOME_COLUMNS;
1365
+ const updateHint = updateTo === void 0 ? null : /* @__PURE__ */ jsxs3(Text, { color: "yellow", wrap: "truncate-end", children: [
1366
+ "\u25B2 ",
1367
+ "Update available: v",
1368
+ packageVersion(),
1369
+ " ",
1370
+ "\u2192",
1371
+ " v",
1372
+ updateTo,
1373
+ " \xB7 npm i -g ",
1374
+ NPM_PACKAGE_NAME
1375
+ ] });
1321
1376
  return /* @__PURE__ */ jsx4(Box_default, { width: "100%", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: wide ? /* @__PURE__ */ jsxs3(Box_default, { width: "100%", flexDirection: "row", children: [
1322
1377
  /* @__PURE__ */ jsxs3(
1323
1378
  Box_default,
@@ -1364,7 +1419,8 @@ function WelcomeCard({ model, serviceName, workspaceName, columns }) {
1364
1419
  /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/config" }),
1365
1420
  " \xB7 ",
1366
1421
  /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/tasks" })
1367
- ] })
1422
+ ] }),
1423
+ updateHint
1368
1424
  ] })
1369
1425
  ] }) : /* @__PURE__ */ jsxs3(Box_default, { width: "100%", flexDirection: "column", children: [
1370
1426
  /* @__PURE__ */ jsx4(Text, { bold: true, color: FLAVOR_ACCENT, children: "\u25C6 Flavor Code" }),
@@ -1381,7 +1437,8 @@ function WelcomeCard({ model, serviceName, workspaceName, columns }) {
1381
1437
  " setup \xB7 ",
1382
1438
  /* @__PURE__ */ jsx4(Text, { color: "cyan", children: "/help" }),
1383
1439
  " commands"
1384
- ] })
1440
+ ] }),
1441
+ updateHint
1385
1442
  ] }) });
1386
1443
  }
1387
1444
 
@@ -1738,6 +1795,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
1738
1795
  const [customQuestionActive, setCustomQuestionActive] = useState2(false);
1739
1796
  const [columns, setColumns] = useState2(stdout?.columns ?? 80);
1740
1797
  const [rows, setRows] = useState2(stdout?.rows ?? 24);
1798
+ const [updateTo, setUpdateTo] = useState2();
1741
1799
  const [transcript, dispatch] = useReducer(transcriptReducer, void 0, createTranscriptState);
1742
1800
  const scrollRef = useRef4(null);
1743
1801
  const taskScrollRef = useRef4(null);
@@ -1910,6 +1968,15 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
1910
1968
  };
1911
1969
  }, [runtime, revision]);
1912
1970
  useEffect3(() => installSigintHandler(process, interrupt), [interrupt]);
1971
+ useEffect3(() => {
1972
+ let disposed = false;
1973
+ void checkForUpdate(packageVersion()).then((version) => {
1974
+ if (version !== void 0 && !disposed) setUpdateTo(version);
1975
+ });
1976
+ return () => {
1977
+ disposed = true;
1978
+ };
1979
+ }, []);
1913
1980
  useEffect3(() => {
1914
1981
  if (runtime?.services.ideContext === void 0) {
1915
1982
  setIdeContext(void 0);
@@ -2293,6 +2360,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2293
2360
  workspaceName: basename3(workspace),
2294
2361
  completed: transcript.completed,
2295
2362
  ...transcript.active === void 0 ? {} : { active: transcript.active },
2363
+ ...updateTo === void 0 ? {} : { updateTo },
2296
2364
  columns,
2297
2365
  rows
2298
2366
  }
@@ -2306,6 +2374,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
2306
2374
  workspaceName: basename3(workspace),
2307
2375
  completed: transcript.completed,
2308
2376
  ...transcript.active === void 0 ? {} : { active: transcript.active },
2377
+ ...updateTo === void 0 ? {} : { updateTo },
2309
2378
  input,
2310
2379
  pastedBlocks,
2311
2380
  imageAttachments,
@@ -2339,6 +2408,7 @@ function StartingLayout({
2339
2408
  workspaceName,
2340
2409
  completed,
2341
2410
  active,
2411
+ updateTo,
2342
2412
  columns,
2343
2413
  rows
2344
2414
  }) {
@@ -2349,6 +2419,7 @@ function StartingLayout({
2349
2419
  workspaceName,
2350
2420
  completed,
2351
2421
  ...active === void 0 ? {} : { active },
2422
+ ...updateTo === void 0 ? {} : { updateTo },
2352
2423
  input: "",
2353
2424
  promptCursor: 0,
2354
2425
  columns,
@@ -2428,6 +2499,7 @@ function TerminalLayout({
2428
2499
  model,
2429
2500
  serviceName,
2430
2501
  workspaceName,
2502
+ updateTo,
2431
2503
  completed,
2432
2504
  active,
2433
2505
  input,
@@ -2480,7 +2552,7 @@ function TerminalLayout({
2480
2552
  const promptMaxLines = Math.max(1, bottomMaxRows - fixedBottomRows);
2481
2553
  return /* @__PURE__ */ jsxs4(Box_default, { height: rows, width: "100%", flexDirection: "column", overflow: "hidden", children: [
2482
2554
  /* @__PURE__ */ jsxs4(ScrollBox_default, { ...scrollRef === void 0 ? {} : { ref: scrollRef }, flexGrow: 1, flexDirection: "column", stickyScroll: true, children: [
2483
- showWelcome ? /* @__PURE__ */ jsx5(WelcomeCard, { model, ...serviceName === void 0 ? {} : { serviceName }, workspaceName, columns }) : /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
2555
+ showWelcome ? /* @__PURE__ */ jsx5(WelcomeCard, { model, ...serviceName === void 0 ? {} : { serviceName }, workspaceName, ...updateTo === void 0 ? {} : { updateTo }, columns }) : /* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
2484
2556
  "flavor \xB7 ",
2485
2557
  model,
2486
2558
  " \xB7 ",
@@ -28548,7 +28548,13 @@ function terminalName() {
28548
28548
  var env = { terminal: terminalName() };
28549
28549
 
28550
28550
  // src/utils/semver.ts
28551
- import { gte as semverGte } from "semver";
28551
+ import { gt as semverGt, gte as semverGte, valid as semverValid } from "semver";
28552
+ function gt(a, b) {
28553
+ return semverGt(a, b, { loose: true });
28554
+ }
28555
+ function isValidVersion(value) {
28556
+ return semverValid(value, { loose: true }) !== null;
28557
+ }
28552
28558
 
28553
28559
  // src/claude-ink/clearTerminal.ts
28554
28560
  var CURSOR_HOME_WINDOWS = csi(0, "f");
@@ -35489,6 +35495,8 @@ export {
35489
35495
  stripAnsi,
35490
35496
  ScrollBox_default,
35491
35497
  instances_default,
35498
+ gt,
35499
+ isValidVersion,
35492
35500
  osc,
35493
35501
  OSC2 as OSC,
35494
35502
  TerminalWriteContext,