flavor-code 1.2.14 → 1.2.16

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.
@@ -4,7 +4,7 @@ import {
4
4
  message,
5
5
  redactErrorText,
6
6
  redactSecrets
7
- } from "./chunk-4YXDGGIC.js";
7
+ } from "./chunk-5SRARNAC.js";
8
8
 
9
9
  // src/rpc/server.ts
10
10
  import { createInterface } from "readline";
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import { createRequire } from "node:module"; const require = createRequire(impor
3
3
  import {
4
4
  FlavorRpcServer,
5
5
  TraceRecorder
6
- } from "./chunk-KL6TR2KG.js";
6
+ } from "./chunk-PGS3M32Y.js";
7
7
  import {
8
8
  staticTaskLines
9
9
  } from "./chunk-KKIBYDJI.js";
@@ -22,7 +22,7 @@ import {
22
22
  packageVersion,
23
23
  redactErrorText,
24
24
  runPalBroker
25
- } from "./chunk-4YXDGGIC.js";
25
+ } from "./chunk-5SRARNAC.js";
26
26
  import {
27
27
  McpServerConfigSchema,
28
28
  McpServerNameSchema,
@@ -43,10 +43,71 @@ import { posix, resolve as resolve3 } from "path";
43
43
  import { fileURLToPath } from "url";
44
44
  import { Command, Option } from "commander";
45
45
 
46
+ // src/utils/crash-guard.ts
47
+ import { mkdirSync, writeFileSync } from "fs";
48
+ import { join } from "path";
49
+ var installed = false;
50
+ function installCrashGuard(options = {}) {
51
+ if (installed) return;
52
+ installed = true;
53
+ const crashLogDir = () => {
54
+ try {
55
+ return join((options.workspace ?? process.cwd)(), ".flavor");
56
+ } catch {
57
+ return process.cwd();
58
+ }
59
+ };
60
+ const writeCrashLog = (kind, detail) => {
61
+ try {
62
+ const dir = crashLogDir();
63
+ mkdirSync(dir, { recursive: true });
64
+ const path = join(dir, `crash-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "")}-${process.pid}.log`);
65
+ writeFileSync(path, [
66
+ `kind: ${kind}`,
67
+ `version: ${process.version}`,
68
+ `platform: ${process.platform}`,
69
+ `time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
70
+ "",
71
+ detail
72
+ ].join("\n"), { encoding: "utf8", mode: 384 });
73
+ return path;
74
+ } catch {
75
+ return void 0;
76
+ }
77
+ };
78
+ const restoreTerminal = () => {
79
+ try {
80
+ if (process.stdout.isTTY === true) process.stdout.write("\x1B[?25h\x1B[?1049l");
81
+ } catch {
82
+ }
83
+ };
84
+ const describe = (reason) => {
85
+ if (reason instanceof Error) return `${reason.name}: ${reason.message}
86
+ ${reason.stack ?? ""}`;
87
+ return String(reason);
88
+ };
89
+ const crash = (kind, reason) => {
90
+ const detail = describe(reason);
91
+ const logPath = writeCrashLog(kind, detail);
92
+ restoreTerminal();
93
+ try {
94
+ const safe = redactErrorText(detail.split("\n").slice(0, 3).join("\n"));
95
+ process.stderr.write(`flavor crashed (${kind}): ${safe}
96
+ `);
97
+ if (logPath !== void 0) process.stderr.write(`crash log: ${logPath}
98
+ `);
99
+ } catch {
100
+ }
101
+ process.exit(1);
102
+ };
103
+ process.on("unhandledRejection", (reason) => crash("unhandledRejection", reason));
104
+ process.on("uncaughtException", (error) => crash("uncaughtException", error));
105
+ }
106
+
46
107
  // src/skills/manager.ts
47
108
  import { lstat, mkdir, readFile, readdir, realpath, rm, writeFile } from "fs/promises";
48
109
  import { homedir } from "os";
49
- import { isAbsolute, join, relative, resolve, sep } from "path";
110
+ import { isAbsolute, join as join2, relative, resolve, sep } from "path";
50
111
  import { stringify } from "yaml";
51
112
  var SkillManager = class {
52
113
  #workspace;
@@ -69,7 +130,7 @@ var SkillManager = class {
69
130
  async create(draft) {
70
131
  const value = parseDraft(draft);
71
132
  const projectRoot = this.#projectRoot();
72
- const directory = join(projectRoot, value.name);
133
+ const directory = join2(projectRoot, value.name);
73
134
  await mkdir(projectRoot, { recursive: true, mode: 448 });
74
135
  try {
75
136
  await mkdir(directory, { mode: 448 });
@@ -78,7 +139,7 @@ var SkillManager = class {
78
139
  throw error;
79
140
  }
80
141
  try {
81
- await writeFile(join(directory, "SKILL.md"), renderSkill(value), { encoding: "utf8", flag: "wx", mode: 384 });
142
+ await writeFile(join2(directory, "SKILL.md"), renderSkill(value), { encoding: "utf8", flag: "wx", mode: 384 });
82
143
  await this.#persistEnabled(value.name, true);
83
144
  return this.get(value.name);
84
145
  } catch (error) {
@@ -96,7 +157,7 @@ var SkillManager = class {
96
157
  throw error;
97
158
  });
98
159
  if (!info.isDirectory() || info.isSymbolicLink()) throw new Error(`Project skill path is not a real directory: ${validName}`);
99
- const skillFile = join(directory, "SKILL.md");
160
+ const skillFile = join2(directory, "SKILL.md");
100
161
  const fileInfo = await lstat(skillFile);
101
162
  if (!fileInfo.isFile() || fileInfo.isSymbolicLink()) throw new Error(`Project skill file is not a real file: ${validName}`);
102
163
  await writeFile(skillFile, renderSkill(value), { encoding: "utf8", mode: 384 });
@@ -128,12 +189,12 @@ var SkillManager = class {
128
189
  async #registry() {
129
190
  const loaded = await loadConfig({ cwd: this.#workspace, home: this.#home });
130
191
  const [globalPluginRoots, projectPluginRoots] = await Promise.all([
131
- discoverPluginSkillRoots(join(this.#home, ".flavor-code", "plugins")),
132
- discoverPluginSkillRoots(join(this.#workspace, ".flavor", "plugins"))
192
+ discoverPluginSkillRoots(join2(this.#home, ".flavor-code", "plugins")),
193
+ discoverPluginSkillRoots(join2(this.#workspace, ".flavor", "plugins"))
133
194
  ]);
134
195
  return {
135
196
  registry: new SkillRegistry({
136
- globalRoots: [join(this.#home, ".flavor-code", "skills"), ...globalPluginRoots],
197
+ globalRoots: [join2(this.#home, ".flavor-code", "skills"), ...globalPluginRoots],
137
198
  projectRoots: [this.#projectRoot(), ...projectPluginRoots]
138
199
  }),
139
200
  disabled: new Set(loaded.config.skills.disabled)
@@ -149,10 +210,10 @@ var SkillManager = class {
149
210
  };
150
211
  }
151
212
  #projectRoot() {
152
- return join(this.#workspace, ".flavor", "skills");
213
+ return join2(this.#workspace, ".flavor", "skills");
153
214
  }
154
215
  #projectSkillDirectory(name) {
155
- return join(this.#projectRoot(), name);
216
+ return join2(this.#projectRoot(), name);
156
217
  }
157
218
  };
158
219
  function parseName(value) {
@@ -193,9 +254,9 @@ async function discoverPluginSkillRoots(directory) {
193
254
  const roots = [];
194
255
  for (const entry of entries) {
195
256
  if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
196
- const pluginRoot = await realpath(join(directory, entry.name));
257
+ const pluginRoot = await realpath(join2(directory, entry.name));
197
258
  try {
198
- const manifest = PluginManifestSchema.parse(JSON.parse(await readFile(join(pluginRoot, "flavor-plugin.json"), "utf8")));
259
+ const manifest = PluginManifestSchema.parse(JSON.parse(await readFile(join2(pluginRoot, "flavor-plugin.json"), "utf8")));
199
260
  for (const contribution of manifest.contributes.skillRoots) {
200
261
  const candidate = resolve(pluginRoot, contribution.path);
201
262
  const info = await lstat(candidate);
@@ -312,11 +373,11 @@ function parseMemoryType(value) {
312
373
  }
313
374
 
314
375
  // src/mcp/config-manager.ts
315
- import { join as join2 } from "path";
376
+ import { join as join3 } from "path";
316
377
  var ProjectMcpConfigManager = class {
317
378
  path;
318
379
  constructor(workspace) {
319
- this.path = join2(workspace, ".flavor", "flavor.json");
380
+ this.path = join3(workspace, ".flavor", "flavor.json");
320
381
  }
321
382
  async list() {
322
383
  const document = await readRecoverableFile(this.path, (raw) => parseDocument(this.path, raw));
@@ -800,7 +861,7 @@ async function runInteractiveCli(props) {
800
861
  const [{ render, AlternateScreen }, { createElement }, { App }] = await Promise.all([
801
862
  import("./claude-ink-ORUA7GWG.js"),
802
863
  import("react"),
803
- import("./app-UJAGMKD5.js")
864
+ import("./app-7ZCJ3UOI.js")
804
865
  ]);
805
866
  const instance = await render(createElement(
806
867
  AlternateScreen,
@@ -936,6 +997,7 @@ function safeError(error) {
936
997
  if (process.argv[1]) {
937
998
  const scriptPath = fileURLToPath(import.meta.url);
938
999
  if (realpathSync(scriptPath) === realpathSync(process.argv[1])) {
1000
+ installCrashGuard();
939
1001
  try {
940
1002
  await createProgram().parseAsync(process.argv);
941
1003
  } catch (error) {