flavor-code 1.2.3 → 1.2.5

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.
Files changed (37) hide show
  1. package/README.md +369 -1090
  2. package/README.zh-CN.md +369 -0
  3. package/dist/{app-SCHNJSXI.js → app-3DXEGSS7.js} +15 -9
  4. package/dist/{chunk-XGCFBGBB.js → chunk-3TYRDK34.js} +43 -38
  5. package/dist/{chunk-MVIMQEQT.js → chunk-HFR2WS6T.js} +0 -1
  6. package/dist/{chunk-DM64TM4Z.js → chunk-KKIBYDJI.js} +0 -1
  7. package/dist/{chunk-VOCZVFP7.js → chunk-N2S7USST.js} +0 -1
  8. package/dist/{chunk-XS2JU6S3.js → chunk-NVLYFU6P.js} +3 -4
  9. package/dist/{chunk-JZ322RCJ.js → chunk-S32JRDZK.js} +0 -1
  10. package/dist/{chunk-AHUOGT4I.js → chunk-Z3BW52MK.js} +1 -2
  11. package/dist/{claude-ink-ZL4UZMFY.js → claude-ink-WPWPEL5A.js} +3 -4
  12. package/dist/cli.js +9 -10
  13. package/dist/desktop/main.js +41 -36
  14. package/dist/desktop/preload.cjs +0 -1
  15. package/dist/desktop-renderer/assets/index-C66pDvHs.js +1 -2
  16. package/dist/desktop-renderer/index.html +14 -14
  17. package/dist/{devtools-SXJBSV2N.js → devtools-4QTPKBKK.js} +0 -1
  18. package/dist/{load-WQGNTCHC.js → load-XC5JYYBQ.js} +2 -3
  19. package/dist/sdk/index.js +5 -6
  20. package/package.json +7 -1
  21. package//346/212/200/346/234/257/346/226/271/346/241/210/346/212/245/345/221/212.md +1 -1
  22. package/dist/app-SCHNJSXI.js.map +0 -1
  23. package/dist/chunk-AHUOGT4I.js.map +0 -1
  24. package/dist/chunk-DM64TM4Z.js.map +0 -1
  25. package/dist/chunk-JZ322RCJ.js.map +0 -1
  26. package/dist/chunk-MVIMQEQT.js.map +0 -1
  27. package/dist/chunk-VOCZVFP7.js.map +0 -1
  28. package/dist/chunk-XGCFBGBB.js.map +0 -1
  29. package/dist/chunk-XS2JU6S3.js.map +0 -1
  30. package/dist/claude-ink-ZL4UZMFY.js.map +0 -1
  31. package/dist/cli.js.map +0 -1
  32. package/dist/desktop/main.js.map +0 -1
  33. package/dist/desktop/preload.cjs.map +0 -1
  34. package/dist/desktop-renderer/assets/index-C66pDvHs.js.map +0 -1
  35. package/dist/devtools-SXJBSV2N.js.map +0 -1
  36. package/dist/load-WQGNTCHC.js.map +0 -1
  37. package/dist/sdk/index.js.map +0 -1
@@ -2953,10 +2953,12 @@ function getToolCategory(name) {
2953
2953
  return isNetworkTool(name) ? "network" : CATEGORY_MAP[name] ?? "unknown";
2954
2954
  }
2955
2955
  var PermissionEngine = class {
2956
+ #lexicalWorkspace;
2956
2957
  #workspace;
2957
2958
  #mode;
2958
2959
  constructor(options) {
2959
2960
  const root = resolve2(options.workspace);
2961
+ this.#lexicalWorkspace = root;
2960
2962
  this.#workspace = existsSync(root) ? realpathSync.native(root) : root;
2961
2963
  this.#mode = canonicalMode(options.mode ?? "default");
2962
2964
  }
@@ -2977,13 +2979,13 @@ var PermissionEngine = class {
2977
2979
  return { decision: "deny", reason: `${request.tool} requires source and destination paths` };
2978
2980
  }
2979
2981
  for (const path of paths) {
2980
- const classification = classifyPath(this.#workspace, path);
2982
+ const classification = classifyPath(this.#lexicalWorkspace, this.#workspace, path);
2981
2983
  if (classification.escape) return { decision: "deny", reason: classification.reason ?? "Path escapes the workspace" };
2982
2984
  if (request.agent === "subagent" && !classification.inside) {
2983
2985
  return { decision: "deny", reason: "Subagents are restricted to the workspace" };
2984
2986
  }
2985
2987
  }
2986
- const inside = paths.every((path) => classifyPath(this.#workspace, path).inside);
2988
+ const inside = paths.every((path) => classifyPath(this.#lexicalWorkspace, this.#workspace, path).inside);
2987
2989
  if (this.#mode === "plan") {
2988
2990
  return READ_TOOLS.has(request.tool) ? { decision: "allow" } : { decision: "deny", reason: "Plan mode is read-only" };
2989
2991
  }
@@ -3010,11 +3012,11 @@ var PermissionEngine = class {
3010
3012
  const analysis = request.args === void 0 ? analyzeCommand(request.command ?? "") : analyzeArgumentCommand(request.command ?? "", request.args);
3011
3013
  if (request.agent === "subagent") {
3012
3014
  if (request.cwd === void 0) return { decision: "ask", reason: "Subagent shell commands require an explicit workspace cwd" };
3013
- const cwd = classifyPath(this.#workspace, request.cwd);
3015
+ const cwd = classifyPath(this.#lexicalWorkspace, this.#workspace, request.cwd);
3014
3016
  if (cwd.escape || !cwd.inside) return { decision: "deny", reason: "Subagent shell cwd must remain in the workspace" };
3015
3017
  if (analysis.destructive) return { decision: "deny", reason: "Destructive commands are forbidden for subagents" };
3016
3018
  if (analysis.wrapped || analysis.opaque || !isRoutineCommand(analysis.command)) return { decision: "ask", reason: "Subagent shell command requires main-Agent approval" };
3017
- const argumentDecision = assessRoutineArguments(analysis.command, request.cwd, this.#workspace);
3019
+ const argumentDecision = assessRoutineArguments(analysis.command, request.cwd, this.#lexicalWorkspace, this.#workspace);
3018
3020
  if (argumentDecision !== "allow") {
3019
3021
  return argumentDecision === "deny" ? { decision: "deny", reason: "Subagent command arguments escape the workspace" } : { decision: "ask", reason: "Ambiguous subagent command arguments require main-Agent approval" };
3020
3022
  }
@@ -3026,12 +3028,12 @@ var PermissionEngine = class {
3026
3028
  if (analysis.wrapped || analysis.opaque) return ask(this.#mode, "Shell wrapper requires approval");
3027
3029
  if (this.#mode === "bypassPermissions") return { decision: "allow" };
3028
3030
  if ((this.#mode === "acceptEdits" || this.#mode === "auto") && isRoutineCommand(analysis.command)) {
3029
- const cwd = request.cwd ?? this.#workspace;
3030
- const cwdClassification = classifyPath(this.#workspace, cwd);
3031
+ const cwd = request.cwd ?? this.#lexicalWorkspace;
3032
+ const cwdClassification = classifyPath(this.#lexicalWorkspace, this.#workspace, cwd);
3031
3033
  if (cwdClassification.escape || !cwdClassification.inside) {
3032
3034
  return { decision: "deny", reason: "Routine command cwd must remain in the workspace" };
3033
3035
  }
3034
- const argumentDecision = assessRoutineArguments(analysis.command, cwd, this.#workspace);
3036
+ const argumentDecision = assessRoutineArguments(analysis.command, cwd, this.#lexicalWorkspace, this.#workspace);
3035
3037
  if (argumentDecision === "deny") return { decision: "deny", reason: "Routine command arguments escape the workspace" };
3036
3038
  if (argumentDecision === "ask") return ask(this.#mode, "Ambiguous routine command arguments require approval");
3037
3039
  return { decision: "allow" };
@@ -3068,16 +3070,16 @@ function analyzeArgumentCommand(executable, args) {
3068
3070
  }
3069
3071
  return { command, destructive: isForbiddenCommand(command), opaque: false, wrapped: false };
3070
3072
  }
3071
- function classifyPath(workspace, input) {
3072
- const candidate = resolve2(workspace, input);
3073
- const lexicalInside = isWithin(workspace, candidate);
3073
+ function classifyPath(lexicalWorkspace, physicalWorkspace, input) {
3074
+ const candidate = resolve2(lexicalWorkspace, input);
3075
+ const lexicalInside = isWithin(lexicalWorkspace, candidate);
3074
3076
  const traversal = input.split(/[\\/]+/).includes("..");
3075
- const startsInWorkspace = pathStartsWith(workspace, input);
3077
+ const startsInWorkspace = pathStartsWith(lexicalWorkspace, input);
3076
3078
  if ((!isAbsolute(input) || startsInWorkspace) && traversal && !lexicalInside) {
3077
3079
  return { inside: false, escape: true, reason: "Path traversal escapes the workspace" };
3078
3080
  }
3079
3081
  const physical = resolvePhysical(candidate);
3080
- const physicalInside = isWithin(workspace, physical);
3082
+ const physicalInside = isWithin(physicalWorkspace, physical);
3081
3083
  if (lexicalInside && !physicalInside) return { inside: false, escape: true, reason: "Symlink escapes the workspace" };
3082
3084
  return { inside: physicalInside, escape: false };
3083
3085
  }
@@ -3167,7 +3169,7 @@ function isRoutineCommand(command) {
3167
3169
  if (command.executable === "go") return first === "test";
3168
3170
  return ["pytest", "vitest", "jest", "eslint", "tsc"].includes(command.executable);
3169
3171
  }
3170
- function assessRoutineArguments(command, cwd, workspace) {
3172
+ function assessRoutineArguments(command, cwd, lexicalWorkspace, physicalWorkspace) {
3171
3173
  const args = routineArguments(command);
3172
3174
  if (args === void 0) return "ask";
3173
3175
  const pathOptions = /* @__PURE__ */ new Set([
@@ -3192,7 +3194,7 @@ function assessRoutineArguments(command, cwd, workspace) {
3192
3194
  const option2 = equals[1]?.toLowerCase() ?? "";
3193
3195
  const value = equals[2] ?? "";
3194
3196
  if (!pathOptions.has(option2)) return "ask";
3195
- const decision = assessArgumentPath(value, cwd, workspace);
3197
+ const decision = assessArgumentPath(value, cwd, lexicalWorkspace, physicalWorkspace);
3196
3198
  if (decision !== "allow") return decision;
3197
3199
  continue;
3198
3200
  }
@@ -3200,14 +3202,14 @@ function assessRoutineArguments(command, cwd, workspace) {
3200
3202
  if (option !== void 0 && pathOptions.has(option)) {
3201
3203
  const value = args[index + 1];
3202
3204
  if (value === void 0 || value.startsWith("-")) return "ask";
3203
- const decision = assessArgumentPath(value, cwd, workspace);
3205
+ const decision = assessArgumentPath(value, cwd, lexicalWorkspace, physicalWorkspace);
3204
3206
  if (decision !== "allow") return decision;
3205
3207
  index += 1;
3206
3208
  continue;
3207
3209
  }
3208
3210
  if (arg.startsWith("-")) continue;
3209
3211
  if (looksLikePath(arg)) {
3210
- const decision = assessArgumentPath(arg, cwd, workspace);
3212
+ const decision = assessArgumentPath(arg, cwd, lexicalWorkspace, physicalWorkspace);
3211
3213
  if (decision !== "allow") return decision;
3212
3214
  continue;
3213
3215
  }
@@ -3225,10 +3227,10 @@ function routineArguments(command) {
3225
3227
  if (["pytest", "vitest", "jest", "eslint", "tsc"].includes(command.executable)) return command.args;
3226
3228
  return void 0;
3227
3229
  }
3228
- function assessArgumentPath(value, cwd, workspace) {
3230
+ function assessArgumentPath(value, cwd, lexicalWorkspace, physicalWorkspace) {
3229
3231
  if (value.length === 0) return "ask";
3230
3232
  const resolved = resolve2(cwd, value);
3231
- const classification = classifyPath(workspace, resolved);
3233
+ const classification = classifyPath(lexicalWorkspace, physicalWorkspace, resolved);
3232
3234
  return classification.escape || !classification.inside ? "deny" : "allow";
3233
3235
  }
3234
3236
  function looksLikePath(value) {
@@ -3477,7 +3479,8 @@ var ToolRuntime = class {
3477
3479
  } catch {
3478
3480
  }
3479
3481
  }
3480
- if (pre.decision === "ask" || permission.decision === "ask") {
3482
+ const sessionAllowed = this.#alwaysAllowed.has(getToolCategory(tool.name));
3483
+ if (!sessionAllowed && (pre.decision === "ask" || permission.decision === "ask")) {
3481
3484
  const reason = [pre.reason, permission.reason].filter((value) => value !== void 0).join("\n") || "Approval required";
3482
3485
  const requestDecision = await this.#hooks.emit({
3483
3486
  version: 1,
@@ -3502,8 +3505,7 @@ var ToolRuntime = class {
3502
3505
  throw signal.reason;
3503
3506
  } else {
3504
3507
  const category = getToolCategory(tool.name);
3505
- if (this.#alwaysAllowed.has(category)) {
3506
- } else if (this.#approve === void 0) {
3508
+ if (this.#approve === void 0) {
3507
3509
  return this.#fail(tool.name, input, context.agent, "permission_denied", reason);
3508
3510
  } else {
3509
3511
  const decision = await this.#approve({ ...request, reason }, signal);
@@ -8251,9 +8253,11 @@ var SkillRegistry = class {
8251
8253
  for (const configuredRoot of roots) {
8252
8254
  const root = resolve11(configuredRoot);
8253
8255
  let entries;
8256
+ let physicalRoot = root;
8254
8257
  try {
8255
8258
  const rootInfo = await lstat5(root);
8256
8259
  if (rootInfo.isSymbolicLink() || !rootInfo.isDirectory()) throw new Error("Skill root must be a real directory");
8260
+ physicalRoot = await realpath4(root);
8257
8261
  entries = await readdir4(root, { withFileTypes: true });
8258
8262
  } catch (error) {
8259
8263
  if (isMissing(error)) continue;
@@ -8266,12 +8270,12 @@ var SkillRegistry = class {
8266
8270
  try {
8267
8271
  if (entry2.isSymbolicLink()) throw new Error("Symlinked skill directories are not allowed");
8268
8272
  if (!entry2.isDirectory()) continue;
8269
- const physicalRoot = await realpath4(skillRoot);
8270
- if (!isWithin3(root, physicalRoot)) throw new Error("Skill directory escapes its registry root");
8273
+ const physicalSkillRoot = await realpath4(skillRoot);
8274
+ if (!isWithin3(physicalRoot, physicalSkillRoot)) throw new Error("Skill directory escapes its registry root");
8271
8275
  const skillFile = resolve11(skillRoot, "SKILL.md");
8272
8276
  const parsed = await readFrontmatterFile(
8273
8277
  skillFile,
8274
- physicalRoot,
8278
+ physicalSkillRoot,
8275
8279
  this.#options.maxMetadataBytes,
8276
8280
  this.#options.openFile
8277
8281
  );
@@ -8282,7 +8286,7 @@ var SkillRegistry = class {
8282
8286
  name: parsed.name,
8283
8287
  description: parsed.description,
8284
8288
  source,
8285
- root: physicalRoot,
8289
+ root: physicalSkillRoot,
8286
8290
  disableModelInvocation: parsed.disableModelInvocation
8287
8291
  }),
8288
8292
  skillFile
@@ -10430,19 +10434,20 @@ function createReadTool(workspace, options = {}) {
10430
10434
  if (startLine !== void 0 && endLine !== void 0 && endLine < startLine) {
10431
10435
  throw new Error(`endLine (${endLine}) must not be below startLine (${startLine})`);
10432
10436
  }
10433
- const contents = await readBounded2(path, maxBytes, signal, openFile2);
10437
+ const rangeRequested = startLine !== void 0 || endLine !== void 0;
10438
+ const windowBytes = rangeRequested ? Math.max(maxBytes, Math.min(info.size, MAX_READ_BYTES)) : maxBytes;
10439
+ const contents = await readBounded2(path, windowBytes, signal, openFile2);
10434
10440
  if (isBinary(contents)) throw new Error("Cannot read binary file as text");
10435
- const textEnd = utf8SafeEnd(contents, maxBytes);
10436
- const truncated = contents.length > maxBytes;
10441
+ const textEnd = utf8SafeEnd(contents, windowBytes);
10442
+ const truncated = contents.length > windowBytes;
10437
10443
  const text = contents.subarray(0, textEnd).toString("utf8").replaceAll("\r\n", "\n");
10438
10444
  const lines = text.split("\n");
10439
10445
  if (lines.at(-1) === "") lines.pop();
10440
10446
  const availableLines = lines.length;
10441
- const rangeRequested = startLine !== void 0 || endLine !== void 0;
10442
10447
  const start = startLine ?? 1;
10443
10448
  const end = Math.min(endLine ?? availableLines, availableLines);
10444
10449
  if (rangeRequested && start > availableLines) {
10445
- throw new Error(`startLine (${start}) is beyond the ${availableLines} line${availableLines === 1 ? "" : "s"} available${truncated ? ` in this read (truncated at ${maxBytes} bytes)` : " in this file"}`);
10450
+ throw new Error(`startLine (${start}) is beyond the ${availableLines} line${availableLines === 1 ? "" : "s"} available${truncated ? ` in this read (truncated at ${windowBytes} bytes)` : " in this file"}`);
10446
10451
  }
10447
10452
  if (rangeRequested && end < start) {
10448
10453
  throw new Error(`endLine (${endLine}) must not be below startLine (${start})`);
@@ -10458,13 +10463,13 @@ function createReadTool(workspace, options = {}) {
10458
10463
  record.ranges = mergeRange(record.ranges, start, end);
10459
10464
  }
10460
10465
  if (rangeRequested) {
10461
- const header = `[Lines ${start}-${end} of ${availableLines}${truncated ? ` visible in this read (truncated at ${maxBytes} bytes)` : ""}]`;
10466
+ const header = `[Lines ${start}-${end} of ${availableLines}${truncated ? ` visible in this read (truncated at ${windowBytes} bytes)` : ""}]`;
10462
10467
  return `${header}
10463
10468
 
10464
10469
  ${lines.slice(start - 1, end).join("\n")}`;
10465
10470
  }
10466
10471
  if (truncated) {
10467
- return `[Truncated to ${maxBytes} bytes. File is ${info.size} bytes total. Request a higher maxBytes or read a specific range with startLine/endLine.]
10472
+ return `[Truncated to ${windowBytes} bytes. File is ${info.size} bytes total. Request a higher maxBytes or read a specific range with startLine/endLine.]
10468
10473
 
10469
10474
  ${text}`;
10470
10475
  }
@@ -10512,6 +10517,7 @@ function createEditTool(workspace, options = {}) {
10512
10517
  paths: (input) => [guard.lexical(input.path)],
10513
10518
  execute: async (input, signal) => {
10514
10519
  abortIfNeeded(signal);
10520
+ const displayPath = guard.lexical(input.path);
10515
10521
  const path = await guard.existing(input.path);
10516
10522
  const contents = await readText(path);
10517
10523
  const hasCRLF = contents.includes("\r\n");
@@ -10527,11 +10533,11 @@ function createEditTool(workspace, options = {}) {
10527
10533
  }
10528
10534
  const updatedLF = contentsLF.slice(0, first) + newTextLF + contentsLF.slice(first + oldTextLF.length);
10529
10535
  const updated = hasCRLF ? updatedLF.replace(/\n/g, "\r\n") : updatedLF;
10530
- await options.beforeCommit?.({ path, before: contents, after: updated, kind: "update" }, signal);
10536
+ await options.beforeCommit?.({ path: displayPath, before: contents, after: updated, kind: "update" }, signal);
10531
10537
  await atomicWrite(path, updated, signal);
10532
10538
  return withToolPresentation(
10533
- { path, replacements: 1 },
10534
- buildFileChangePresentation(path, contents, updated, "update")
10539
+ { path: displayPath, replacements: 1 },
10540
+ buildFileChangePresentation(displayPath, contents, updated, "update")
10535
10541
  );
10536
10542
  }
10537
10543
  };
@@ -17790,4 +17796,3 @@ app.on("before-quit", () => {
17790
17796
  app.on("window-all-closed", () => {
17791
17797
  if (process.platform !== "darwin") app.quit();
17792
17798
  });
17793
- //# sourceMappingURL=main.js.map
@@ -87,4 +87,3 @@ var api = {
87
87
  }
88
88
  };
89
89
  import_electron.contextBridge.exposeInMainWorld("flavorDesktop", api);
90
- //# sourceMappingURL=preload.cjs.map
@@ -140,5 +140,4 @@ Describe when and how the agent should use this skill.`,disableModelInvocation:!
140
140
  `)}function _l(e){return`command`in e?[e.command,...e.args].join(` `):``}function vl(e){return`url`in e?e.url:``}function yl(e){return e instanceof Error?e.message:String(e)}var bl={sessions:[],diagnostics:[],models:[]},xl=[`default`,`acceptEdits`,`plan`,`bypassPermissions`,`auto`,`bubble`],Sl=nl.map(e=>({name:e,description:rl[e]})),Cl=5,wl=5*1024*1024,Tl=20*1024*1024,El=new Set([`image/png`,`image/jpeg`,`image/webp`]);function Dl(e,t){return[e.trim(),...t.map((e,t)=>`[Image #${t+1}]`)].filter(Boolean).join(`
141
141
  `)}function Ol({attachments:e,onRemove:t}){return(0,N.jsx)(`div`,{className:`image-attachment-strip`,"aria-label":`待发送图片`,children:e.map((e,n)=>(0,N.jsxs)(`figure`,{className:`image-attachment-chip`,children:[(0,N.jsx)(`img`,{src:e.previewUrl,alt:e.name}),(0,N.jsxs)(`figcaption`,{children:[(0,N.jsxs)(`strong`,{children:[`[Image #`,n+1,`]`]}),(0,N.jsx)(`span`,{children:e.name})]}),(0,N.jsx)(`button`,{type:`button`,onClick:()=>t(e.id),"aria-label":`移除 ${e.name}`,title:`移除图片`,children:`×`})]},e.id))})}function kl(){let[e,t]=(0,_.useState)(bl),[n,r]=(0,_.useState)(x),[i,a]=(0,_.useState)(``),[o,s]=(0,_.useState)([]),[c,l]=(0,_.useState)(!0),[u,d]=(0,_.useState)(),[f,p]=(0,_.useState)(!1),[m,h]=(0,_.useState)(!1),[g,v]=(0,_.useState)(),[y,b]=(0,_.useState)(),[C,w]=(0,_.useState)(!1),[ee,T]=(0,_.useState)(0),[te,E]=(0,_.useState)(),[ne,re]=(0,_.useState)([]),[ie,ae]=(0,_.useState)([]),[oe,se]=(0,_.useState)(0),[ce,D]=(0,_.useState)(),[O,le]=(0,_.useState)(),[ue,de]=(0,_.useState)(0),[k,A]=(0,_.useState)(`conversation`),he=(0,_.useRef)(null),ge=(0,_.useRef)(null),_e=(0,_.useRef)(void 0),ve=(0,_.useRef)(new Set),ye=(0,_.useRef)(!1),be=(0,_.useCallback)(e=>{a(e),E(void 0),D(void 0)},[]);(0,_.useEffect)(()=>()=>{for(let e of ve.current)URL.revokeObjectURL(e);ve.current.clear()},[]);let j=(0,_.useCallback)(e=>{s(t=>{let n=t.find(t=>t.id===e);return n!==void 0&&(URL.revokeObjectURL(n.previewUrl),ve.current.delete(n.previewUrl)),t.filter(t=>t.id!==e)})},[]),xe=(0,_.useCallback)(()=>{s(e=>{for(let t of e)URL.revokeObjectURL(t.previewUrl),ve.current.delete(t.previewUrl);return[]})},[]),Se=(0,_.useCallback)(async e=>{if(e.length===0)return;let t=Cl-o.length;if(t<=0||e.length>t){d(`每条消息最多添加 ${Cl} 张图片。`);return}if(o.reduce((e,t)=>e+Math.floor(t.dataBase64.length*3/4),0)+e.reduce((e,t)=>e+t.size,0)>Tl){d(`单条消息的图片总大小不能超过 20 MiB。`);return}try{let t=await Promise.all(e.map(q));for(let e of t)ve.current.add(e.previewUrl);s(e=>[...e,...t].slice(0,Cl)),d(void 0)}catch(e){d(Xl(e))}},[o]);(0,_.useEffect)(()=>{let e=he.current;if(!e)return;let t=e=>{e.deltaY<0?ye.current=!0:requestAnimationFrame(()=>{let e=he.current;e&&e.scrollHeight-e.scrollTop-e.clientHeight<8&&(ye.current=!1)})};return e.addEventListener(`wheel`,t,{passive:!0}),()=>e.removeEventListener(`wheel`,t)},[]),(0,_.useEffect)(()=>{let e=window.flavorDesktop.onEvent(e=>{jl(e,_e,t,r,d)});return window.flavorDesktop.bootstrap().then(e=>{_e.current=e.activeSession?.sessionId,t(e)}).catch(e=>d(Xl(e))).finally(()=>l(!1)),e},[]),(0,_.useEffect)(()=>{ye.current||he.current?.scrollTo({top:he.current.scrollHeight,behavior:`smooth`})},[n]),(0,_.useEffect)(()=>{let e=!1;return window.flavorDesktop.listFiles().then(t=>{e||ae(ln(t))}).catch(()=>{}),()=>{e=!0}},[e.workspace]),(0,_.useEffect)(()=>{let t=!1;return e.workspace===void 0?(re([]),()=>{t=!0}):(window.flavorDesktop.listSkills().then(e=>{t||re(e)}).catch(()=>{t||re([])}),()=>{t=!0})},[e.workspace,k]);let Ce=e.activeSession?.busy??!1,we=(0,_.useMemo)(()=>fe(e.sessions),[e.sessions]),Te=(0,_.useMemo)(()=>Jt(Sl,[],ne.filter(e=>e.enabled)),[ne]),Ee=(0,_.useMemo)(()=>Ce||e.approval!==void 0||e.questions!==void 0||te===i?null:Xt(i,ue,Te,ee),[i,ue,ee,te,Ce,e.approval,e.questions,Te]),De=(0,_.useMemo)(()=>Ce||e.approval!==void 0||e.questions!==void 0||ce===i||Ee!==null?null:un(i,ue,ie,oe),[i,ue,oe,ce,Ce,e.approval,e.questions,ie,Ee]),Oe=Ee===null?Yt(i,Te,!1):0,ke=(0,_.useCallback)(e=>{let t=Qt(i,ue,e);a(t.text),E(t.text),T(0),de(t.cursor),setTimeout(()=>{let e=ge.current;e!==null&&(e.focus(),e.setSelectionRange(e.value.length,e.value.length))},0)},[i,ue]),Ae=(0,_.useCallback)(()=>{E(i)},[i]),je=(0,_.useCallback)(e=>{T(t=>Zt(t,e,Ee?.items.length??0))},[Ee]),Me=(0,_.useCallback)(e=>{let t=fn(i,ue,e);a(t.text),D(t.text),se(0),le(t.span),de(t.cursor),setTimeout(()=>{let e=ge.current;e!==null&&(e.focus(),e.setSelectionRange(e.value.length,e.value.length))},0)},[i,ue]),Ne=(0,_.useCallback)(()=>{D(i)},[i]),Pe=(0,_.useCallback)(e=>{se(t=>dn(t,e,De?.items.length??0))},[De]),Fe=async()=>{d(void 0);try{let e=await window.flavorDesktop.chooseWorkspace();e!==void 0&&(xe(),t(e),r(x()),p(!1),A(`conversation`))}catch(e){d(Xl(e))}},Ie=async e=>{d(void 0);try{let n=await window.flavorDesktop.startSession(e?.sessionId);xe(),t(n.snapshot),r(S(x(),{type:`restore`,state:n.restoredTranscript})),p(!1),A(`conversation`),setTimeout(()=>ge.current?.focus(),0)}catch(e){d(Xl(e))}},Le=async(n,s)=>{let c=(n??i).trim(),l=n===void 0?o:[];if(!(!c&&l.length===0)){d(void 0);try{let i=e;if(i.activeSession===void 0){let e=await window.flavorDesktop.startSession();i=e.snapshot,t(i),r(S(x(),{type:`restore`,state:e.restoredTranscript}))}let o=s??(Ce?`steer`:`prompt`);if(l.length>0&&o!==`prompt`)throw Error(`图片只能随新消息发送,不能作为运行中的引导或后续消息。`);o===`prompt`&&r(e=>S(e,{type:`submit`,prompt:Dl(c,l)})),n===void 0&&a(``),await window.flavorDesktop.submit(c,o,l.map(({name:e,mediaType:t,dataBase64:n})=>({name:e,mediaType:t,dataBase64:n}))),l.length>0&&xe()}catch(e){let t=Xl(e);d(t),r(e=>S(e,{type:`submit-error`,message:t}))}}},Re=e=>void Le(`/permissions ${e}`),ze=async e=>{d(void 0);try{t(await window.flavorDesktop.switchModel(e))}catch(e){d(Xl(e))}},Be=async()=>{if(!(Ce||e.activeSession===void 0)){d(void 0);try{await window.flavorDesktop.finishTask()}catch(e){d(Xl(e))}}},Ve=async e=>{d(void 0);try{let n=await window.flavorDesktop.addModel(e);t(n.snapshot)}catch(e){throw d(Xl(e)),e}},He=(e,t)=>{let n=t.currentTarget.getBoundingClientRect();window.flavorDesktop.showAppMenu(e,Math.round(n.left),Math.round(n.bottom))},Ue=async()=>{if(!(y===void 0||C)){w(!0),d(void 0);try{let n=y.sessionId===e.activeSession?.sessionId,i=await window.flavorDesktop.deleteSession(y.sessionId);t(i),n&&r(x()),b(void 0),v(void 0)}catch(e){d(Xl(e))}finally{w(!1)}}};return(0,N.jsxs)(`div`,{className:`app-frame`,children:[(0,N.jsx)(Al,{railCollapsed:m,onToggleRail:()=>h(e=>!e),onMenu:He}),(0,N.jsxs)(`div`,{className:`desktop-shell`,"data-rail-collapsed":m,children:[(0,N.jsx)(`button`,{className:`rail-scrim`,"data-open":f,onClick:()=>p(!1),"aria-label":`关闭项目栏`}),(0,N.jsxs)(`aside`,{className:`project-rail`,"data-open":f,children:[(0,N.jsxs)(`div`,{className:`brand-row`,children:[(0,N.jsx)(Yl,{}),(0,N.jsx)(`strong`,{children:`Flavor Code`}),(0,N.jsx)(`span`,{className:`brand-chevron`,children:`⌄`})]}),(0,N.jsxs)(`nav`,{className:`primary-actions`,"aria-label":`主要操作`,children:[(0,N.jsxs)(`button`,{className:`rail-action rail-action-primary`,disabled:e.workspace===void 0,onClick:()=>void Ie(),children:[(0,N.jsx)(`span`,{className:`action-icon`,children:`+`}),(0,N.jsx)(`span`,{children:`新建任务`}),(0,N.jsx)(`kbd`,{children:`Ctrl N`})]}),(0,N.jsxs)(`button`,{className:`rail-action`,onClick:()=>void Fe(),children:[(0,N.jsx)(`span`,{className:`action-icon`,children:`⌂`}),(0,N.jsx)(`span`,{children:`打开项目`})]}),(0,N.jsxs)(`button`,{className:`rail-action`,"data-active":k===`skills`,onClick:()=>{A(`skills`),p(!1)},disabled:e.workspace===void 0,children:[(0,N.jsx)(`span`,{className:`action-icon`,children:`◇`}),(0,N.jsx)(`span`,{children:`技能`})]}),(0,N.jsxs)(`button`,{className:`rail-action`,"data-active":k===`memory`,onClick:()=>{A(`memory`),p(!1)},disabled:e.workspace===void 0,children:[(0,N.jsx)(`span`,{className:`action-icon`,children:`⌁`}),(0,N.jsx)(`span`,{children:`长期记忆`})]}),(0,N.jsxs)(`button`,{className:`rail-action`,"data-active":k===`mcp`,onClick:()=>{A(`mcp`),p(!1)},disabled:e.workspace===void 0,children:[(0,N.jsx)(`span`,{className:`action-icon`,children:`◎`}),(0,N.jsx)(`span`,{children:`MCP 服务`})]})]}),(0,N.jsxs)(`div`,{className:`sessions-scroll`,children:[(0,N.jsx)(`div`,{className:`rail-section-title`,children:`项目`}),e.workspace===void 0?(0,N.jsx)(`button`,{className:`empty-project`,onClick:()=>void Fe(),children:`选择一个本地文件夹开始`}):(0,N.jsxs)(N.Fragment,{children:[(0,N.jsxs)(`div`,{className:`project-heading`,children:[(0,N.jsx)(`span`,{className:`folder-icon`,children:`▱`}),(0,N.jsx)(`span`,{children:me(e.workspace)})]}),we.length===0&&(0,N.jsx)(`p`,{className:`no-sessions`,children:`还没有任务`}),we.map(t=>(0,N.jsxs)(`section`,{className:`session-group`,children:[(0,N.jsx)(`h2`,{children:t.label}),t.sessions.map(t=>(0,N.jsxs)(`div`,{className:`session-item-shell`,onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||v(void 0)},children:[(0,N.jsxs)(`button`,{className:`session-item`,"data-active":t.sessionId===e.activeSession?.sessionId,onClick:()=>void Ie(t),children:[(0,N.jsx)(`span`,{children:pe(t)}),(0,N.jsx)(`time`,{children:$l(t.updatedAt)})]}),(0,N.jsx)(`button`,{className:`session-more`,"aria-label":`管理会话:${pe(t)}`,"aria-expanded":g===t.sessionId,onClick:()=>v(e=>e===t.sessionId?void 0:t.sessionId),children:`•••`}),g===t.sessionId&&(0,N.jsx)(`div`,{className:`session-menu`,role:`menu`,children:(0,N.jsx)(`button`,{role:`menuitem`,className:`danger-item`,disabled:Ce&&t.sessionId===e.activeSession?.sessionId,onClick:()=>{b(t),v(void 0)},children:`删除会话`})})]},t.sessionId))]},t.label))]})]}),(0,N.jsxs)(`div`,{className:`rail-footer`,children:[(0,N.jsx)(`span`,{className:`avatar`,children:`F`}),(0,N.jsx)(`span`,{children:`本地工作区`}),(0,N.jsx)(`button`,{title:`帮助`,children:`?`})]})]}),(0,N.jsxs)(`main`,{className:`workspace-panel`,children:[k===`skills`&&e.workspace!==void 0?(0,N.jsx)(al,{onClose:()=>A(`conversation`),onError:d}):k===`memory`&&e.workspace!==void 0?(0,N.jsx)(ll,{onClose:()=>A(`conversation`),onError:d}):k===`mcp`&&e.workspace!==void 0?(0,N.jsx)(dl,{onClose:()=>A(`conversation`),onError:d}):(0,N.jsxs)(N.Fragment,{children:[(0,N.jsxs)(`header`,{className:`workspace-header`,children:[(0,N.jsx)(`button`,{className:`mobile-rail-toggle`,onClick:()=>p(!0),"aria-label":`打开项目栏`,children:`☰`}),(0,N.jsx)(`div`,{className:`workspace-breadcrumb`,children:(0,N.jsx)(`span`,{children:me(e.workspace)})}),(0,N.jsxs)(`div`,{className:`header-actions`,children:[(0,N.jsx)(`button`,{className:`finish-task-button`,onClick:()=>void Be(),disabled:Ce||e.activeSession===void 0,title:`评估并完成当前任务`,children:`完成任务`}),(0,N.jsx)(`button`,{title:`更多选项`,children:`•••`})]})]}),(0,N.jsx)(`div`,{className:`conversation-scroll`,ref:he,children:c?(0,N.jsx)(Gl,{}):e.workspace===void 0?(0,N.jsx)(Wl,{onOpen:Fe}):n.completed.length===0&&n.active===void 0?(0,N.jsx)(Ul,{project:me(e.workspace),onStart:e=>void Le(e)}):(0,N.jsxs)(`div`,{className:`conversation-column`,children:[n.completed.map(e=>(0,N.jsx)(Ml,{turn:e},e.id)),n.active!==void 0&&(0,N.jsx)(Ml,{turn:n.active,active:!0})]})}),e.diagnostics.length>0&&(0,N.jsxs)(`details`,{className:`diagnostics`,children:[(0,N.jsxs)(`summary`,{children:[e.diagnostics.length,` 条启动提示`]}),(0,N.jsx)(`pre`,{children:e.diagnostics.join(`
142
142
  `)})]}),(0,N.jsx)(Ll,{input:i,setInput:be,onSend:e=>void Le(void 0,e),busy:Ce,onInterrupt:()=>void window.flavorDesktop.interrupt(),inputRef:ge,snapshot:e,attachments:o,onAddImages:e=>void Se(e),onRemoveImage:j,setModel:ze,addModel:Ve,setPermission:Re,slashCompletion:Ee,onSlashSelect:ke,onSlashDismiss:Ae,onSlashMove:je,mentionCompletion:De,onMentionSelect:Me,onMentionDismiss:Ne,onMentionMove:Pe,mentionSpan:O,setMentionSpan:le,completedTokenLen:Oe,cursorPos:ue,setCursorPos:de})]}),u!==void 0&&(0,N.jsxs)(`div`,{className:`error-toast`,role:`alert`,children:[(0,N.jsx)(`span`,{children:`!`}),(0,N.jsx)(`p`,{children:u}),(0,N.jsx)(`button`,{onClick:()=>d(void 0),children:`×`})]})]})]}),e.approval!==void 0&&(0,N.jsx)(zl,{approval:e.approval,onResolve:e=>void window.flavorDesktop.resolveApproval(e)}),e.questions!==void 0&&(0,N.jsx)(Bl,{questions:e.questions,onAnswer:e=>void window.flavorDesktop.answerQuestions(e)}),e.memoryReviews!==void 0&&e.memoryReviews.length>0&&(0,N.jsx)(Vl,{reviews:e.memoryReviews,autoDismissSeconds:e.memoryAutoDismissSeconds??0,onResolve:(e,t)=>{window.flavorDesktop.resolveMemoryReview(e,t).catch(e=>d(Xl(e)))}}),y!==void 0&&(0,N.jsx)(Y,{session:y,deleting:C,onCancel:()=>b(void 0),onDelete:()=>void Ue()})]})}function Al({railCollapsed:e,onToggleRail:t,onMenu:n}){return(0,N.jsxs)(`header`,{className:`window-titlebar`,children:[(0,N.jsx)(`button`,{className:`titlebar-icon sidebar-toggle`,"data-collapsed":e,onClick:t,"aria-label":e?`显示项目栏`:`隐藏项目栏`,title:e?`显示项目栏`:`隐藏项目栏`,children:(0,N.jsxs)(`svg`,{viewBox:`0 0 16 16`,"aria-hidden":`true`,children:[(0,N.jsx)(`rect`,{x:`2.5`,y:`2.5`,width:`11`,height:`11`,rx:`2`}),(0,N.jsx)(`path`,{d:`M6 3v10`})]})}),(0,N.jsx)(`button`,{className:`titlebar-icon nav-button`,disabled:!0,"aria-label":`后退`,children:(0,N.jsx)(`span`,{children:`‹`})}),(0,N.jsx)(`button`,{className:`titlebar-icon nav-button`,disabled:!0,"aria-label":`前进`,children:(0,N.jsx)(`span`,{children:`›`})}),(0,N.jsxs)(`nav`,{className:`titlebar-menus`,"aria-label":`应用菜单`,children:[(0,N.jsx)(`button`,{onClick:e=>n(`file`,e),children:`文件`}),(0,N.jsx)(`button`,{onClick:e=>n(`edit`,e),children:`编辑`}),(0,N.jsx)(`button`,{onClick:e=>n(`view`,e),children:`视图`}),(0,N.jsx)(`button`,{onClick:e=>n(`help`,e),children:`帮助`})]})]})}function jl(e,t,n,r,i){e.type===`snapshot`?(t.current=e.snapshot.activeSession?.sessionId,n(e.snapshot)):e.type===`session-started`?(t.current=e.payload.sessionId,n(e.payload.snapshot),r(S(x(),{type:`restore`,state:e.payload.restoredTranscript}))):e.type===`session-output`?r(n=>ge(n,t.current,e)):e.type===`runtime-error`&&(e.sessionId===void 0||e.sessionId===t.current)&&i(e.message)}function Ml({turn:e,active:t=!1}){let n=t?e.blocks:e.blocks.filter(e=>e.kind!==`status`||e.task===void 0);return(0,N.jsxs)(`article`,{className:`turn`,"data-active":t,"data-kind":e.kind??`conversation`,children:[(0,N.jsx)(`div`,{className:`user-message`,children:(0,N.jsx)(`span`,{children:e.prompt})}),(0,N.jsxs)(`div`,{className:`assistant-message`,children:[(0,N.jsx)(`div`,{className:`assistant-avatar`,children:(0,N.jsx)(Yl,{})}),(0,N.jsxs)(`div`,{className:`turn-content`,children:[n.map((e,t)=>(0,N.jsx)(Nl,{block:e},e.kind===`status`?e.id:`text-${t}`)),t&&n.length===0&&(0,N.jsxs)(`div`,{className:`thinking-line`,children:[(0,N.jsx)(`i`,{}),(0,N.jsx)(`span`,{children:`正在理解任务…`})]})]})]})]})}function Nl({block:e}){if(e.kind===`text`)return(0,N.jsx)(`div`,{className:`assistant-copy`,children:(0,N.jsx)(Wt,{text:e.text})});let t=e.state===`completed`?`✓`:e.state===`failed`?`×`:e.state===`cancelled`?`–`:e.state===`running`?``:`·`;return(0,N.jsxs)(`div`,{className:`activity-card`,"data-state":e.state,"data-tone":e.tone,children:[(0,N.jsx)(`span`,{className:`activity-node`,children:t}),(0,N.jsxs)(`div`,{className:`activity-body`,children:[(0,N.jsxs)(`div`,{className:`activity-title`,children:[(0,N.jsx)(`span`,{children:e.text.replace(/^[·✓×]\s*/,``)}),e.hint&&(0,N.jsx)(`code`,{children:e.hint})]}),e.progress!==void 0&&(0,N.jsx)(`div`,{className:`progress-track`,children:(0,N.jsx)(`i`,{style:{width:`${e.progress}%`}})}),e.presentation&&(0,N.jsx)(Fl,{presentation:e.presentation}),e.tool&&(0,N.jsxs)(`details`,{className:`tool-details`,children:[(0,N.jsx)(`summary`,{children:`调用详情`}),(0,N.jsx)(`label`,{children:`Input`}),(0,N.jsx)(`pre`,{children:Pl(e.tool.input)}),e.tool.result===void 0?null:(0,N.jsxs)(N.Fragment,{children:[(0,N.jsx)(`label`,{children:`Result`}),(0,N.jsx)(`pre`,{children:Pl(e.tool.result)})]})]}),e.details&&(0,N.jsxs)(`details`,{className:`timeline-details`,children:[(0,N.jsx)(`summary`,{children:`压缩摘要`}),(0,N.jsx)(Wt,{text:e.details})]})]})]})}function Pl(e,t=1e4){let n;try{n=JSON.stringify(e,null,2)??`undefined`}catch{n=String(e)}return n.length<=t?n:`${n.slice(0,t)}…`}function Fl({presentation:e}){let t=e.operation===`delete`,n=e.operation===`create`?`新建`:e.operation===`delete`?`删除`:`修改`,r=e.path.replace(/^.*[/\\]/,``),i=t?1:Math.max(1,...e.lines.map(e=>Math.max(e.oldLine??0,e.newLine??0))).toString().length;return(0,N.jsxs)(`details`,{className:`diff-preview`,children:[(0,N.jsxs)(`summary`,{children:[(0,N.jsx)(`span`,{className:`diff-marker ${t?`diff-delete`:`diff-add`}`,children:`●`}),(0,N.jsx)(`span`,{className:`diff-label`,children:n}),(0,N.jsx)(`span`,{className:`diff-path`,children:r}),(0,N.jsxs)(`span`,{className:`diff-counts`,children:[!t&&(0,N.jsxs)(`span`,{className:`diff-added-count`,children:[`+`,e.added]}),!t&&e.removed>0&&(0,N.jsxs)(`span`,{className:`diff-removed-count`,children:[` −`,e.removed]}),t&&(0,N.jsxs)(`span`,{className:`diff-removed-count`,children:[`−`,e.removed]})]})]}),t?null:(0,N.jsx)(`div`,{className:`diff-body`,children:e.lines.map((e,t)=>(0,N.jsx)(Il,{line:e,lineWidth:i},t))})]})}function Il({line:e,lineWidth:t}){let n=e.kind===`removed`||e.kind===`context`?e.oldLine:e.newLine,r=e.kind===`removed`?`-`:e.kind===`added`?`+`:e.kind===`omitted`?`…`:` `;return(0,N.jsxs)(`div`,{className:`diff-row ${e.kind===`added`?`diff-row-added`:e.kind===`removed`?`diff-row-removed`:e.kind===`omitted`?`diff-row-omitted`:`diff-row-context`}`,children:[(0,N.jsx)(`span`,{className:`diff-line-number`,children:String(n??``).padStart(t)}),(0,N.jsx)(`span`,{className:`diff-line-marker`,children:r}),(0,N.jsx)(`span`,{className:`diff-line-text`,children:e.text})]})}function Ll(e){let t=e.snapshot.workspace===void 0,[n,r]=(0,_.useState)(!1),i=(0,_.useRef)(null),a=e.slashCompletion!==null,o=e.mentionCompletion!==null,s=a||o,c=e.completedTokenLen>0,l=c?e.input.slice(0,e.completedTokenLen):void 0,u=l?.startsWith(`/`)?l.slice(1).trim():l?.trim(),d=c?void 0:e.mentionSpan,f=d!==void 0&&d.start>=0&&d.end>d.start&&d.start<e.input.length&&d.end<=e.input.length&&e.input.slice(d.start,d.end)===e.input.slice(d.start,d.end),p=f?e.input.slice(0,d.start):``,m=f?e.input.slice(d.start,d.end):``,h=f?e.input.slice(d.end):``,g=m.startsWith(`@`)?m.slice(1).trim():m,v=c?e.input.slice(e.completedTokenLen):f?h:e.input,y=c?l.length:f?d.start+m.length:0,b=e=>y+e,x=t=>{if(a){if(t.key===`ArrowDown`){t.preventDefault(),e.onSlashMove(1);return}if(t.key===`ArrowUp`){t.preventDefault(),e.onSlashMove(-1);return}if(t.key===`Tab`||t.key===`Enter`){t.preventDefault();let n=e.slashCompletion?.items[e.slashCompletion?.selectedIndex??0];n!==void 0&&e.onSlashSelect(n.name);return}if(t.key===`Escape`){t.preventDefault(),e.onSlashDismiss();return}}if(o){if(t.key===`ArrowDown`){t.preventDefault(),e.onMentionMove(1);return}if(t.key===`ArrowUp`){t.preventDefault(),e.onMentionMove(-1);return}if(t.key===`Tab`||t.key===`Enter`){t.preventDefault();let n=e.mentionCompletion?.items[e.mentionCompletion?.selectedIndex??0];n!==void 0&&e.onMentionSelect(n);return}if(t.key===`Escape`){t.preventDefault(),e.onMentionDismiss();return}}let n=t.target,r=n.selectionStart,i=n.selectionEnd;if(t.key===`Backspace`&&r===i&&!s){if(c){let n=$t(e.input,e.completedTokenLen,b(r));if(n!==null){t.preventDefault(),e.setInput(n.text),e.setCursorPos(n.cursor);return}}if(f&&r===0){t.preventDefault();let n=p+h;e.setInput(n),e.setMentionSpan(void 0),e.setCursorPos(p.length);return}}t.key===`Enter`&&!t.shiftKey&&(t.preventDefault(),e.onSend(t.altKey?`followUp`:e.busy?`steer`:void 0))},S=(t,n)=>{let r;if(r=c?l+t:f?p+m+t:t,f){let t=p+m;r.startsWith(t)||e.setMentionSpan(void 0)}e.setInput(r),e.setCursorPos(b(n))},C=t=>{e.setCursorPos(b(t))},w=(0,N.jsx)(`textarea`,{ref:e.inputRef,className:`composer-textarea`,value:v,onChange:e=>S(e.target.value,e.target.selectionStart),onSelect:e=>C(e.target.selectionStart),onKeyDown:x,onPaste:t=>{let n=Rl(t.clipboardData.files);n.length!==0&&(t.preventDefault(),e.onAddImages(n))},onClick:e=>C(e.target.selectionStart),placeholder:t?`先打开一个项目`:c||f?``:`给 Flavor 一个任务,或输入 / 查看命令`,disabled:t,rows:1}),ee=c?(0,N.jsxs)(`div`,{className:`composer-input-row`,children:[(0,N.jsx)(`span`,{className:`slash-tag`,children:u}),w]}):f?(0,N.jsxs)(`div`,{className:`composer-input-row`,children:[p.length>0&&(0,N.jsx)(`span`,{className:`composer-plain-text`,children:p}),(0,N.jsx)(`span`,{className:`mention-tag`,children:g}),w]}):w;return(0,N.jsxs)(`div`,{className:`composer-wrap`,onDragEnter:e=>{K(e.dataTransfer)&&(e.preventDefault(),r(!0))},onDragOver:e=>{K(e.dataTransfer)&&e.preventDefault()},onDragLeave:e=>{e.currentTarget.contains(e.relatedTarget)||r(!1)},onDrop:t=>{let n=Rl(t.dataTransfer.files);n.length!==0&&(t.preventDefault(),r(!1),e.onAddImages(n))},children:[a&&(0,N.jsx)(rn,{completion:e.slashCompletion,onSelect:e.onSlashSelect,onDismiss:e.onSlashDismiss}),o&&(0,N.jsx)(sn,{completion:e.mentionCompletion,onSelect:e.onMentionSelect,onDismiss:e.onMentionDismiss}),(0,N.jsxs)(`div`,{className:`composer${c||f?` has-tag`:``}`,"data-busy":e.busy,"data-image-drag":n,children:[e.attachments.length>0&&(0,N.jsx)(Ol,{attachments:e.attachments,onRemove:e.onRemoveImage}),ee,(0,N.jsxs)(`div`,{className:`composer-tools`,children:[(0,N.jsx)(`input`,{ref:i,className:`image-file-input`,type:`file`,accept:`image/png,image/jpeg,image/webp`,multiple:!0,onChange:t=>{e.onAddImages(Rl(t.target.files)),t.target.value=``}}),(0,N.jsx)(`button`,{type:`button`,className:`attach-button image-attach-button`,title:`添加图片(也可粘贴或拖入)`,"aria-label":`添加图片`,onClick:()=>i.current?.click(),disabled:t||e.busy||e.attachments.length>=Cl,children:`▧`}),(0,N.jsx)(`button`,{className:`attach-button`,title:`在提示中输入 @ 引用项目文件`,onClick:()=>{e.setInput(`${e.input}${e.input?` `:``}@`),setTimeout(()=>{let t=e.inputRef.current;t!==null&&(t.focus(),t.setSelectionRange(t.value.length,t.value.length))},0)},disabled:t,children:`+`}),(0,N.jsxs)(`div`,{className:`composer-context`,children:[(0,N.jsxs)(`span`,{className:`context-item`,children:[`▱ `,me(e.snapshot.workspace)]}),(0,N.jsx)(`span`,{className:`context-item`,children:`▣ 本地`})]}),(0,N.jsxs)(`div`,{className:`composer-controls`,children:[(0,N.jsx)(Ql,{models:e.snapshot.models,activeModel:e.snapshot.activeSession?.mainModel,busy:e.busy,onSelect:e.setModel,onAdd:e.addModel}),(0,N.jsx)(`select`,{"aria-label":`权限模式`,value:e.snapshot.activeSession?.permissionMode??`default`,disabled:e.busy||e.snapshot.activeSession===void 0,onChange:t=>e.setPermission(t.target.value),children:xl.map(e=>(0,N.jsx)(`option`,{value:e,children:A(e)},e))}),e.busy&&(0,N.jsxs)(`span`,{className:`queue-count`,title:`引导 + 后续消息`,children:[e.snapshot.activeSession?.queue.steering.length??0,`+`,e.snapshot.activeSession?.queue.followUp.length??0]}),(0,N.jsx)(`button`,{className:`send-button`,onClick:()=>e.onSend(e.busy?`steer`:void 0),disabled:t||!e.input.trim()&&e.attachments.length===0,title:e.busy?`发送引导消息`:`发送`,children:(0,N.jsx)(`span`,{children:`↑`})}),e.busy&&(0,N.jsx)(`button`,{className:`send-button stop-button`,onClick:e.onInterrupt,title:`停止任务`,children:(0,N.jsx)(`span`,{})})]})]})]}),(0,N.jsx)(`p`,{className:`composer-hint`,children:`Enter 发送 · Shift Enter 换行 · 粘贴/拖入图片 · @ 引用文件 · / 调用命令`})]})}function Rl(e){return e===null?[]:Array.from(e).filter(e=>e.type.startsWith(`image/`))}function K(e){return Array.from(e.items).some(e=>e.kind===`file`&&e.type.startsWith(`image/`))}async function q(e){if(!El.has(e.type))throw Error(`不支持 ${e.type||`未知格式`};请选择 PNG、JPEG 或 WebP 图片。`);if(e.size<=0)throw Error(`${e.name} 是空文件。`);if(e.size>wl)throw Error(`${e.name} 超过单图 5 MiB 限制。`);let t=J(new Uint8Array(await e.arrayBuffer())),n=URL.createObjectURL(e);return{id:globalThis.crypto?.randomUUID?.()??`${Date.now()}-${Math.random()}`,name:e.name,mediaType:e.type,dataBase64:t,previewUrl:n}}function J(e){let t=``,n=32768;for(let r=0;r<e.length;r+=n)t+=String.fromCharCode(...e.subarray(r,r+n));return btoa(t)}function Y({session:e,deleting:t,onCancel:n,onDelete:r}){return(0,N.jsx)(`div`,{className:`modal-layer`,children:(0,N.jsxs)(`section`,{className:`decision-sheet delete-session-sheet`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`delete-session-title`,children:[(0,N.jsx)(`div`,{className:`sheet-icon danger`,children:`×`}),(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`p`,{className:`sheet-kicker`,children:`删除历史会话`}),(0,N.jsxs)(`h2`,{id:`delete-session-title`,children:[`删除“`,pe(e),`”?`]}),(0,N.jsx)(`p`,{children:`此会话的消息和任务记录将从当前项目中永久删除,此操作无法撤销。`}),(0,N.jsxs)(`div`,{className:`sheet-actions`,children:[(0,N.jsx)(`button`,{disabled:t,onClick:n,children:`取消`}),(0,N.jsx)(`button`,{className:`danger`,disabled:t,onClick:r,children:t?`正在删除…`:`删除会话`})]})]})]})})}var X=new Set([`Delete`,`Move`]);function zl({approval:e,onResolve:t}){let n=X.has(e.tool);return(0,N.jsx)(`div`,{className:`modal-layer`,children:(0,N.jsxs)(`section`,{className:`decision-sheet`,role:`dialog`,"aria-modal":`true`,"aria-labelledby":`approval-title`,children:[(0,N.jsx)(`div`,{className:`sheet-icon warning`,children:`!`}),(0,N.jsxs)(`div`,{children:[(0,N.jsxs)(`p`,{className:`sheet-kicker`,children:[`权限确认 · `,e.agent===`main`?`主 Agent`:`子 Agent`]}),(0,N.jsxs)(`h2`,{id:`approval-title`,children:[`允许执行 `,e.tool,`?`]}),(0,N.jsx)(`p`,{children:e.reason??`这项操作需要你的确认。`}),(e.command||e.paths?.length)&&(0,N.jsxs)(`pre`,{children:[e.command??e.paths?.join(`
143
- `),e.args?.length?` ${e.args.join(` `)}`:``]}),(0,N.jsxs)(`div`,{className:`sheet-actions`,children:[(0,N.jsx)(`button`,{onClick:()=>t(`deny`),children:`拒绝`}),!n&&(0,N.jsx)(`button`,{onClick:()=>t(`always`),children:`始终允许同类操作`}),(0,N.jsx)(`button`,{className:`primary`,onClick:()=>t(`allow`),children:`允许一次`})]})]})]})})}function Bl({questions:e,onAnswer:t}){let[n,r]=(0,_.useState)({}),[i,a]=(0,_.useState)({}),o=e.every((e,t)=>!!n[t]?.trim());return(0,N.jsx)(`div`,{className:`modal-layer`,children:(0,N.jsxs)(`section`,{className:`question-sheet`,role:`dialog`,"aria-modal":`true`,children:[(0,N.jsx)(`p`,{className:`sheet-kicker`,children:`Flavor 需要确认`}),e.map((e,t)=>(0,N.jsxs)(`fieldset`,{children:[(0,N.jsx)(`legend`,{children:e.header}),(0,N.jsx)(`p`,{children:e.question}),(0,N.jsxs)(`div`,{className:`question-options`,children:[e.options.map(e=>(0,N.jsxs)(`button`,{"data-selected":!i[t]&&n[t]===e.label,onClick:()=>{a(e=>({...e,[t]:!1})),r(n=>({...n,[t]:e.label}))},children:[(0,N.jsx)(`strong`,{children:e.label}),(0,N.jsx)(`span`,{children:e.description})]},e.label)),(0,N.jsxs)(`button`,{"data-selected":i[t]===!0,onClick:()=>{a(e=>({...e,[t]:!0})),r(e=>({...e,[t]:``}))},children:[(0,N.jsx)(`strong`,{children:`其他(自定义输入)`}),(0,N.jsx)(`span`,{children:`键入你自己的回答`})]}),i[t]===!0&&(0,N.jsx)(`input`,{className:`question-custom-input`,autoFocus:!0,value:n[t]??``,onChange:e=>r(n=>({...n,[t]:e.target.value})),placeholder:`请输入回答`,"aria-label":`${e.header} 自定义回答`})]})]},`${e.header}-${t}`)),(0,N.jsx)(`div`,{className:`sheet-actions`,children:(0,N.jsx)(`button`,{className:`primary`,disabled:!o,onClick:()=>t(n),children:`继续`})})]})})}function Vl({reviews:e,autoDismissSeconds:t,onResolve:n}){return(0,N.jsxs)(`aside`,{className:`memory-review-rail`,"aria-label":`长期记忆写入确认`,children:[(0,N.jsxs)(`header`,{children:[(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`p`,{children:`待确认`}),(0,N.jsx)(`h2`,{children:`长期记忆候选`})]}),(0,N.jsx)(`span`,{children:e.length})]}),(0,N.jsx)(`p`,{className:`memory-review-warning`,children:`以下内容由模型生成,确认前不会写入长期记忆,也不会影响后续会话。`}),(0,N.jsx)(`div`,{className:`memory-review-list`,children:e.map(e=>(0,N.jsxs)(`article`,{children:[(0,N.jsx)(`small`,{children:e.type}),(0,N.jsx)(`p`,{children:e.content}),(0,N.jsx)(Hl,{seconds:t}),(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`button`,{onClick:()=>n(e.id,`dismiss`),children:`忽略`}),(0,N.jsx)(`button`,{className:`primary`,onClick:()=>n(e.id,`accept`),children:`保存`})]})]},e.id))})]})}function Hl({seconds:e}){let[t,n]=(0,_.useState)(e);return(0,_.useEffect)(()=>{if(e<=0)return;n(e);let t=setInterval(()=>n(e=>Math.max(0,e-1)),1e3);return()=>clearInterval(t)},[e]),e<=0?null:(0,N.jsxs)(`small`,{className:`memory-review-countdown`,children:[`未操作将在 `,t,`s 后自动忽略`]})}function Ul({project:e,onStart:t}){return(0,N.jsxs)(`section`,{className:`welcome-state`,children:[(0,N.jsx)(`div`,{className:`welcome-mark`,children:(0,N.jsx)(Yl,{})}),(0,N.jsx)(`p`,{children:`已连接本地项目`}),(0,N.jsxs)(`h1`,{children:[`我们应该在 `,(0,N.jsx)(`u`,{children:e}),` 中构建什么?`]}),(0,N.jsx)(`div`,{className:`starter-grid`,children:de.map(e=>(0,N.jsx)(`button`,{onClick:()=>t(e),children:e},e))})]})}function Wl({onOpen:e}){return(0,N.jsxs)(`section`,{className:`open-state`,children:[(0,N.jsx)(`div`,{className:`welcome-mark`,children:(0,N.jsx)(Yl,{})}),(0,N.jsx)(`h1`,{children:`从一个本地项目开始`}),(0,N.jsx)(`p`,{children:`Flavor 会在你选择的文件夹范围内阅读、修改和运行代码。`}),(0,N.jsx)(`button`,{onClick:e,children:`打开项目`})]})}function Gl(){return(0,N.jsxs)(`div`,{className:`loading-state`,children:[(0,N.jsx)(Yl,{}),(0,N.jsx)(`span`,{children:`正在准备桌面工作区…`})]})}var Kl;function ql(){return Kl??=window.flavorDesktop.appIcon().catch(()=>void 0),Kl}function Jl(){let[e,t]=(0,_.useState)(void 0);return(0,_.useEffect)(()=>{let e=!1;return ql().then(n=>{e||t(n)}),()=>{e=!0}},[]),e}function Yl(){let e=Jl();return e===void 0?(0,N.jsxs)(`svg`,{className:`flavor-mark`,viewBox:`0 0 36 36`,"aria-hidden":`true`,children:[(0,N.jsx)(`path`,{d:`M8 17.5C8 11.7 12.5 7 18 7s10 4.7 10 10.5c0 2.7-1 5.1-2.7 7l1 3.8-4-1.2A9.5 9.5 0 0 1 18 28c-5.5 0-10-4.7-10-10.5Z`}),(0,N.jsx)(`path`,{d:`M16 15l-2 2l2 2`,fill:`none`,stroke:`#1979c9`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`}),(0,N.jsx)(`path`,{d:`M20 15l2 2l-2 2`,fill:`none`,stroke:`#1979c9`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`}),(0,N.jsx)(`path`,{className:`mark-smile`,d:`M14 23c2.5 1.5 5.5 1.5 8 0`}),(0,N.jsx)(`ellipse`,{cx:`22`,cy:`24`,rx:`1.2`,ry:`0.9`,fill:`#f472b6`,stroke:`#ec4899`,strokeWidth:`0.3`,transform:`rotate(15 22 24)`})]}):(0,N.jsx)(`img`,{className:`flavor-mark`,src:e,alt:``,"aria-hidden":`true`})}function Xl(e){return e instanceof Error?e.message:String(e)}function Zl(e){return e?e.split(`:`).at(-1)??e:`选择模型`}function Ql({models:e,activeModel:t,busy:n,onSelect:r,onAdd:i}){let[a,o]=(0,_.useState)(!1),[s,c]=(0,_.useState)(!1),[l,u]=(0,_.useState)(),[d,f]=(0,_.useState)({provider:``,model:``,baseURL:``,apiKey:``,protocol:`openai-compatible`}),p=(e,t)=>{f(n=>({...n,[e]:t})),u(void 0)},m=async e=>{if(e.preventDefault(),s)return;let t=e.currentTarget;c(!0),u(void 0);try{await i(d),o(!1),f({provider:``,model:``,baseURL:``,apiKey:``,protocol:`openai-compatible`}),t.closest(`details`)?.removeAttribute(`open`)}catch(e){u(Xl(e))}finally{c(!1)}};return(0,N.jsxs)(`details`,{className:`model-menu`,children:[(0,N.jsxs)(`summary`,{children:[Zl(t),`⌄`]}),(0,N.jsxs)(`div`,{className:`popover model-popover`,children:[(0,N.jsxs)(`div`,{className:`model-popover-heading`,children:[(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`strong`,{children:a?`添加厂商模型`:`切换主模型`}),(0,N.jsx)(`span`,{children:a?`连接 OpenAI 兼容或 Anthropic 服务`:`DeepSeek 默认可用,也可接入其他厂商`})]}),!a&&(0,N.jsx)(`button`,{type:`button`,onClick:()=>o(!0),disabled:n,children:`+ 新增`})]}),a?(0,N.jsxs)(`form`,{className:`model-provider-form`,onSubmit:e=>void m(e),children:[(0,N.jsxs)(`div`,{className:`model-form-grid`,children:[(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`厂商名称 / ID`}),(0,N.jsx)(`input`,{required:!0,maxLength:64,placeholder:`例如 siliconflow`,value:d.provider,onChange:e=>p(`provider`,e.target.value),pattern:`[A-Za-z0-9][A-Za-z0-9_-]*`})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`模型名称`}),(0,N.jsx)(`input`,{required:!0,maxLength:256,placeholder:`例如 qwen3-coder`,value:d.model,onChange:e=>p(`model`,e.target.value)})]})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`接口协议`}),(0,N.jsxs)(`select`,{value:d.protocol,onChange:e=>p(`protocol`,e.target.value),children:[(0,N.jsx)(`option`,{value:`openai-compatible`,children:`OpenAI 兼容 API`}),(0,N.jsx)(`option`,{value:`anthropic`,children:`Anthropic API`})]})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`Base URL`}),(0,N.jsx)(`input`,{required:!0,type:`url`,maxLength:2048,placeholder:`https://api.example.com/v1`,value:d.baseURL,onChange:e=>p(`baseURL`,e.target.value)})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`API Key`}),(0,N.jsx)(`input`,{required:!0,type:`password`,autoComplete:`off`,maxLength:16384,placeholder:`输入服务密钥`,value:d.apiKey,onChange:e=>p(`apiKey`,e.target.value)})]}),(0,N.jsxs)(`p`,{className:`model-security-note`,children:[(0,N.jsx)(`span`,{children:`◆`}),` 配置同步到当前项目,密钥只加密保存在本机。保存后会新建会话。`]}),l!==void 0&&(0,N.jsx)(`p`,{className:`model-form-error`,role:`alert`,children:l}),(0,N.jsxs)(`div`,{className:`model-form-actions`,children:[(0,N.jsx)(`button`,{type:`button`,onClick:()=>{o(!1),u(void 0)},disabled:s,children:`取消`}),(0,N.jsx)(`button`,{type:`submit`,className:`primary`,disabled:s||n,children:s?`正在连接…`:`保存并切换`})]})]}):(0,N.jsx)(`div`,{className:`model-options`,role:`listbox`,"aria-label":`主模型`,children:e.map(e=>{let i=t===e.id;return(0,N.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":i,className:`model-option`,disabled:n||i,onClick:t=>{r(e.id),t.currentTarget.closest(`details`)?.removeAttribute(`open`)},children:[(0,N.jsxs)(`span`,{className:`model-option-copy`,children:[(0,N.jsx)(`strong`,{children:e.label}),(0,N.jsx)(`small`,{children:e.description})]}),e.source===`custom`&&(0,N.jsx)(`span`,{className:`model-option-badge`,children:`自定义`}),(0,N.jsx)(`span`,{className:`model-option-state`,"aria-hidden":`true`,children:i?`✓`:`→`})]},e.id)})})]})]})}function $l(e){let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`})}var eu=document.getElementById(`root`);if(eu===null)throw Error(`Desktop root element was not found`);(0,v.createRoot)(eu).render((0,N.jsx)(_.StrictMode,{children:(0,N.jsx)(kl,{})}));
144
- //# sourceMappingURL=index-C66pDvHs.js.map
143
+ `),e.args?.length?` ${e.args.join(` `)}`:``]}),(0,N.jsxs)(`div`,{className:`sheet-actions`,children:[(0,N.jsx)(`button`,{onClick:()=>t(`deny`),children:`拒绝`}),!n&&(0,N.jsx)(`button`,{onClick:()=>t(`always`),children:`始终允许同类操作`}),(0,N.jsx)(`button`,{className:`primary`,onClick:()=>t(`allow`),children:`允许一次`})]})]})]})})}function Bl({questions:e,onAnswer:t}){let[n,r]=(0,_.useState)({}),[i,a]=(0,_.useState)({}),o=e.every((e,t)=>!!n[t]?.trim());return(0,N.jsx)(`div`,{className:`modal-layer`,children:(0,N.jsxs)(`section`,{className:`question-sheet`,role:`dialog`,"aria-modal":`true`,children:[(0,N.jsx)(`p`,{className:`sheet-kicker`,children:`Flavor 需要确认`}),e.map((e,t)=>(0,N.jsxs)(`fieldset`,{children:[(0,N.jsx)(`legend`,{children:e.header}),(0,N.jsx)(`p`,{children:e.question}),(0,N.jsxs)(`div`,{className:`question-options`,children:[e.options.map(e=>(0,N.jsxs)(`button`,{"data-selected":!i[t]&&n[t]===e.label,onClick:()=>{a(e=>({...e,[t]:!1})),r(n=>({...n,[t]:e.label}))},children:[(0,N.jsx)(`strong`,{children:e.label}),(0,N.jsx)(`span`,{children:e.description})]},e.label)),(0,N.jsxs)(`button`,{"data-selected":i[t]===!0,onClick:()=>{a(e=>({...e,[t]:!0})),r(e=>({...e,[t]:``}))},children:[(0,N.jsx)(`strong`,{children:`其他(自定义输入)`}),(0,N.jsx)(`span`,{children:`键入你自己的回答`})]}),i[t]===!0&&(0,N.jsx)(`input`,{className:`question-custom-input`,autoFocus:!0,value:n[t]??``,onChange:e=>r(n=>({...n,[t]:e.target.value})),placeholder:`请输入回答`,"aria-label":`${e.header} 自定义回答`})]})]},`${e.header}-${t}`)),(0,N.jsx)(`div`,{className:`sheet-actions`,children:(0,N.jsx)(`button`,{className:`primary`,disabled:!o,onClick:()=>t(n),children:`继续`})})]})})}function Vl({reviews:e,autoDismissSeconds:t,onResolve:n}){return(0,N.jsxs)(`aside`,{className:`memory-review-rail`,"aria-label":`长期记忆写入确认`,children:[(0,N.jsxs)(`header`,{children:[(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`p`,{children:`待确认`}),(0,N.jsx)(`h2`,{children:`长期记忆候选`})]}),(0,N.jsx)(`span`,{children:e.length})]}),(0,N.jsx)(`p`,{className:`memory-review-warning`,children:`以下内容由模型生成,确认前不会写入长期记忆,也不会影响后续会话。`}),(0,N.jsx)(`div`,{className:`memory-review-list`,children:e.map(e=>(0,N.jsxs)(`article`,{children:[(0,N.jsx)(`small`,{children:e.type}),(0,N.jsx)(`p`,{children:e.content}),(0,N.jsx)(Hl,{seconds:t}),(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`button`,{onClick:()=>n(e.id,`dismiss`),children:`忽略`}),(0,N.jsx)(`button`,{className:`primary`,onClick:()=>n(e.id,`accept`),children:`保存`})]})]},e.id))})]})}function Hl({seconds:e}){let[t,n]=(0,_.useState)(e);return(0,_.useEffect)(()=>{if(e<=0)return;n(e);let t=setInterval(()=>n(e=>Math.max(0,e-1)),1e3);return()=>clearInterval(t)},[e]),e<=0?null:(0,N.jsxs)(`small`,{className:`memory-review-countdown`,children:[`未操作将在 `,t,`s 后自动忽略`]})}function Ul({project:e,onStart:t}){return(0,N.jsxs)(`section`,{className:`welcome-state`,children:[(0,N.jsx)(`div`,{className:`welcome-mark`,children:(0,N.jsx)(Yl,{})}),(0,N.jsx)(`p`,{children:`已连接本地项目`}),(0,N.jsxs)(`h1`,{children:[`我们应该在 `,(0,N.jsx)(`u`,{children:e}),` 中构建什么?`]}),(0,N.jsx)(`div`,{className:`starter-grid`,children:de.map(e=>(0,N.jsx)(`button`,{onClick:()=>t(e),children:e},e))})]})}function Wl({onOpen:e}){return(0,N.jsxs)(`section`,{className:`open-state`,children:[(0,N.jsx)(`div`,{className:`welcome-mark`,children:(0,N.jsx)(Yl,{})}),(0,N.jsx)(`h1`,{children:`从一个本地项目开始`}),(0,N.jsx)(`p`,{children:`Flavor 会在你选择的文件夹范围内阅读、修改和运行代码。`}),(0,N.jsx)(`button`,{onClick:e,children:`打开项目`})]})}function Gl(){return(0,N.jsxs)(`div`,{className:`loading-state`,children:[(0,N.jsx)(Yl,{}),(0,N.jsx)(`span`,{children:`正在准备桌面工作区…`})]})}var Kl;function ql(){return Kl??=window.flavorDesktop.appIcon().catch(()=>void 0),Kl}function Jl(){let[e,t]=(0,_.useState)(void 0);return(0,_.useEffect)(()=>{let e=!1;return ql().then(n=>{e||t(n)}),()=>{e=!0}},[]),e}function Yl(){let e=Jl();return e===void 0?(0,N.jsxs)(`svg`,{className:`flavor-mark`,viewBox:`0 0 36 36`,"aria-hidden":`true`,children:[(0,N.jsx)(`path`,{d:`M8 17.5C8 11.7 12.5 7 18 7s10 4.7 10 10.5c0 2.7-1 5.1-2.7 7l1 3.8-4-1.2A9.5 9.5 0 0 1 18 28c-5.5 0-10-4.7-10-10.5Z`}),(0,N.jsx)(`path`,{d:`M16 15l-2 2l2 2`,fill:`none`,stroke:`#1979c9`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`}),(0,N.jsx)(`path`,{d:`M20 15l2 2l-2 2`,fill:`none`,stroke:`#1979c9`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`}),(0,N.jsx)(`path`,{className:`mark-smile`,d:`M14 23c2.5 1.5 5.5 1.5 8 0`}),(0,N.jsx)(`ellipse`,{cx:`22`,cy:`24`,rx:`1.2`,ry:`0.9`,fill:`#f472b6`,stroke:`#ec4899`,strokeWidth:`0.3`,transform:`rotate(15 22 24)`})]}):(0,N.jsx)(`img`,{className:`flavor-mark`,src:e,alt:``,"aria-hidden":`true`})}function Xl(e){return e instanceof Error?e.message:String(e)}function Zl(e){return e?e.split(`:`).at(-1)??e:`选择模型`}function Ql({models:e,activeModel:t,busy:n,onSelect:r,onAdd:i}){let[a,o]=(0,_.useState)(!1),[s,c]=(0,_.useState)(!1),[l,u]=(0,_.useState)(),[d,f]=(0,_.useState)({provider:``,model:``,baseURL:``,apiKey:``,protocol:`openai-compatible`}),p=(e,t)=>{f(n=>({...n,[e]:t})),u(void 0)},m=async e=>{if(e.preventDefault(),s)return;let t=e.currentTarget;c(!0),u(void 0);try{await i(d),o(!1),f({provider:``,model:``,baseURL:``,apiKey:``,protocol:`openai-compatible`}),t.closest(`details`)?.removeAttribute(`open`)}catch(e){u(Xl(e))}finally{c(!1)}};return(0,N.jsxs)(`details`,{className:`model-menu`,children:[(0,N.jsxs)(`summary`,{children:[Zl(t),`⌄`]}),(0,N.jsxs)(`div`,{className:`popover model-popover`,children:[(0,N.jsxs)(`div`,{className:`model-popover-heading`,children:[(0,N.jsxs)(`div`,{children:[(0,N.jsx)(`strong`,{children:a?`添加厂商模型`:`切换主模型`}),(0,N.jsx)(`span`,{children:a?`连接 OpenAI 兼容或 Anthropic 服务`:`DeepSeek 默认可用,也可接入其他厂商`})]}),!a&&(0,N.jsx)(`button`,{type:`button`,onClick:()=>o(!0),disabled:n,children:`+ 新增`})]}),a?(0,N.jsxs)(`form`,{className:`model-provider-form`,onSubmit:e=>void m(e),children:[(0,N.jsxs)(`div`,{className:`model-form-grid`,children:[(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`厂商名称 / ID`}),(0,N.jsx)(`input`,{required:!0,maxLength:64,placeholder:`例如 siliconflow`,value:d.provider,onChange:e=>p(`provider`,e.target.value),pattern:`[A-Za-z0-9][A-Za-z0-9_-]*`})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`模型名称`}),(0,N.jsx)(`input`,{required:!0,maxLength:256,placeholder:`例如 qwen3-coder`,value:d.model,onChange:e=>p(`model`,e.target.value)})]})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`接口协议`}),(0,N.jsxs)(`select`,{value:d.protocol,onChange:e=>p(`protocol`,e.target.value),children:[(0,N.jsx)(`option`,{value:`openai-compatible`,children:`OpenAI 兼容 API`}),(0,N.jsx)(`option`,{value:`anthropic`,children:`Anthropic API`})]})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`Base URL`}),(0,N.jsx)(`input`,{required:!0,type:`url`,maxLength:2048,placeholder:`https://api.example.com/v1`,value:d.baseURL,onChange:e=>p(`baseURL`,e.target.value)})]}),(0,N.jsxs)(`label`,{children:[(0,N.jsx)(`span`,{children:`API Key`}),(0,N.jsx)(`input`,{required:!0,type:`password`,autoComplete:`off`,maxLength:16384,placeholder:`输入服务密钥`,value:d.apiKey,onChange:e=>p(`apiKey`,e.target.value)})]}),(0,N.jsxs)(`p`,{className:`model-security-note`,children:[(0,N.jsx)(`span`,{children:`◆`}),` 配置同步到当前项目,密钥只加密保存在本机。保存后会新建会话。`]}),l!==void 0&&(0,N.jsx)(`p`,{className:`model-form-error`,role:`alert`,children:l}),(0,N.jsxs)(`div`,{className:`model-form-actions`,children:[(0,N.jsx)(`button`,{type:`button`,onClick:()=>{o(!1),u(void 0)},disabled:s,children:`取消`}),(0,N.jsx)(`button`,{type:`submit`,className:`primary`,disabled:s||n,children:s?`正在连接…`:`保存并切换`})]})]}):(0,N.jsx)(`div`,{className:`model-options`,role:`listbox`,"aria-label":`主模型`,children:e.map(e=>{let i=t===e.id;return(0,N.jsxs)(`button`,{type:`button`,role:`option`,"aria-selected":i,className:`model-option`,disabled:n||i,onClick:t=>{r(e.id),t.currentTarget.closest(`details`)?.removeAttribute(`open`)},children:[(0,N.jsxs)(`span`,{className:`model-option-copy`,children:[(0,N.jsx)(`strong`,{children:e.label}),(0,N.jsx)(`small`,{children:e.description})]}),e.source===`custom`&&(0,N.jsx)(`span`,{className:`model-option-badge`,children:`自定义`}),(0,N.jsx)(`span`,{className:`model-option-state`,"aria-hidden":`true`,children:i?`✓`:`→`})]},e.id)})})]})]})}function $l(e){let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toLocaleTimeString(`zh-CN`,{hour:`2-digit`,minute:`2-digit`})}var eu=document.getElementById(`root`);if(eu===null)throw Error(`Desktop root element was not found`);(0,v.createRoot)(eu).render((0,N.jsx)(_.StrictMode,{children:(0,N.jsx)(kl,{})}));
@@ -1,16 +1,16 @@
1
- <!doctype html>
2
- <html lang="zh-CN">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <meta name="color-scheme" content="light" />
7
- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' http://127.0.0.1:* ws://127.0.0.1:*" />
8
- <title>Flavor Code</title>
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <meta name="color-scheme" content="light" />
7
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' http://127.0.0.1:* ws://127.0.0.1:*" />
8
+ <title>Flavor Code</title>
9
9
  <script type="module" crossorigin src="./assets/index-C66pDvHs.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="./assets/index-Cm_ktmXm.css">
11
- </head>
12
- <body>
13
- <div id="root"></div>
14
- </body>
15
- </html>
16
-
11
+ </head>
12
+ <body>
13
+ <div id="root"></div>
14
+ </body>
15
+ </html>
16
+
@@ -1,3 +1,2 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module"; const require = createRequire(import.meta.url);
3
- //# sourceMappingURL=devtools-SXJBSV2N.js.map
@@ -7,8 +7,8 @@ import {
7
7
  setProjectMcpServerDisabled,
8
8
  setProjectProviderConfig,
9
9
  setProjectSkillDisabled
10
- } from "./chunk-MVIMQEQT.js";
11
- import "./chunk-JZ322RCJ.js";
10
+ } from "./chunk-HFR2WS6T.js";
11
+ import "./chunk-S32JRDZK.js";
12
12
  export {
13
13
  loadConfig,
14
14
  redactConfig,
@@ -17,4 +17,3 @@ export {
17
17
  setProjectProviderConfig,
18
18
  setProjectSkillDisabled
19
19
  };
20
- //# sourceMappingURL=load-WQGNTCHC.js.map
package/dist/sdk/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  FlavorRpcServer,
5
5
  TraceRecordSchema,
6
6
  TraceRecorder
7
- } from "../chunk-AHUOGT4I.js";
7
+ } from "../chunk-Z3BW52MK.js";
8
8
  import {
9
9
  AgentMessageQueue,
10
10
  DockerExecutionEnvironment,
@@ -13,10 +13,10 @@ import {
13
13
  WorkspaceCheckpointStore,
14
14
  buildDockerInvocation,
15
15
  createProductionRuntime
16
- } from "../chunk-XGCFBGBB.js";
17
- import "../chunk-MVIMQEQT.js";
18
- import "../chunk-VOCZVFP7.js";
19
- import "../chunk-JZ322RCJ.js";
16
+ } from "../chunk-3TYRDK34.js";
17
+ import "../chunk-HFR2WS6T.js";
18
+ import "../chunk-N2S7USST.js";
19
+ import "../chunk-S32JRDZK.js";
20
20
 
21
21
  // src/trace/replay.ts
22
22
  import { readFile } from "fs/promises";
@@ -50,4 +50,3 @@ export {
50
50
  replayOutputEvents,
51
51
  replayTrace
52
52
  };
53
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "flavor-code",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "author": "YachuanWzh",
5
5
  "type": "module",
6
+ "publishConfig": {
7
+ "registry": "https://registry.npmjs.org"
8
+ },
6
9
  "main": "dist/desktop/main.js",
7
10
  "bin": {
8
11
  "flavor": "dist/cli.js"
@@ -16,7 +19,9 @@
16
19
  },
17
20
  "files": [
18
21
  "dist/",
22
+ "!dist/**/*.map",
19
23
  "README.md",
24
+ "README.zh-CN.md",
20
25
  "技术方案报告.md",
21
26
  "LICENSE"
22
27
  ],
@@ -55,6 +60,7 @@
55
60
  },
56
61
  "files": [
57
62
  "dist/**/*",
63
+ "!dist/**/*.map",
58
64
  "assets/icon.png",
59
65
  "package.json",
60
66
  "README.md",
@@ -1,6 +1,6 @@
1
1
  # flavor-code 技术方案报告
2
2
 
3
- > 版本:1.2.3 | 语言:TypeScript | 运行时:Node.js ≥20 | 包管理器:npm
3
+ > 版本:1.2.4 | 语言:TypeScript | 运行时:Node.js ≥20 | 包管理器:npm
4
4
 
5
5
  ---
6
6