flavor-code 1.2.14 → 1.2.15
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 +8 -3
- package/README.zh-CN.md +8 -3
- package/dist/agent/planner.d.ts +2 -0
- package/dist/{app-UJAGMKD5.js → app-3KW2FTVJ.js} +1 -1
- package/dist/{chunk-4YXDGGIC.js → chunk-5TG3E2EJ.js} +561 -74
- package/dist/{chunk-KL6TR2KG.js → chunk-BKARQJQZ.js} +1 -1
- package/dist/cli.js +78 -16
- package/dist/desktop/main.js +875 -328
- package/dist/desktop-renderer/assets/{index-CcD0D6x0.js → index-BCJjMvbX.js} +1 -1
- package/dist/desktop-renderer/index.html +1 -1
- package/dist/evolve/store.d.ts +26 -0
- package/dist/git/insights.d.ts +52 -0
- package/dist/git/service.d.ts +43 -0
- package/dist/git/tools.d.ts +9 -0
- package/dist/sdk/index.js +2 -2
- package/dist/session/store.d.ts +1 -0
- package/dist/ui/commands.d.ts +8 -2
- package/dist/ui/session.d.ts +2 -0
- package/package.json +1 -1
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-
|
|
6
|
+
} from "./chunk-BKARQJQZ.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-
|
|
25
|
+
} from "./chunk-5TG3E2EJ.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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
132
|
-
discoverPluginSkillRoots(
|
|
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: [
|
|
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
|
|
213
|
+
return join2(this.#workspace, ".flavor", "skills");
|
|
153
214
|
}
|
|
154
215
|
#projectSkillDirectory(name) {
|
|
155
|
-
return
|
|
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(
|
|
257
|
+
const pluginRoot = await realpath(join2(directory, entry.name));
|
|
197
258
|
try {
|
|
198
|
-
const manifest = PluginManifestSchema.parse(JSON.parse(await readFile(
|
|
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
|
|
376
|
+
import { join as join3 } from "path";
|
|
316
377
|
var ProjectMcpConfigManager = class {
|
|
317
378
|
path;
|
|
318
379
|
constructor(workspace) {
|
|
319
|
-
this.path =
|
|
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-
|
|
864
|
+
import("./app-3KW2FTVJ.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) {
|