flavor-code 1.2.2 → 1.2.4

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 (36) hide show
  1. package/README.md +208 -922
  2. package/dist/{app-WC2XXGLM.js → app-N3655H2E.js} +6 -7
  3. package/dist/{chunk-MVIMQEQT.js → chunk-HFR2WS6T.js} +0 -1
  4. package/dist/{chunk-DM64TM4Z.js → chunk-KKIBYDJI.js} +0 -1
  5. package/dist/{chunk-M744K7MK.js → chunk-L5A2NDMT.js} +1 -2
  6. package/dist/{chunk-BU64GNXE.js → chunk-MRISY6KK.js} +29 -14
  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/{claude-ink-ZL4UZMFY.js → claude-ink-WPWPEL5A.js} +3 -4
  11. package/dist/cli.js +9 -10
  12. package/dist/desktop/main.js +27 -12
  13. package/dist/desktop/preload.cjs +0 -1
  14. package/dist/desktop-renderer/assets/index-C66pDvHs.js +1 -2
  15. package/dist/desktop-renderer/index.html +14 -14
  16. package/dist/{devtools-SXJBSV2N.js → devtools-4QTPKBKK.js} +0 -1
  17. package/dist/{load-WQGNTCHC.js → load-XC5JYYBQ.js} +2 -3
  18. package/dist/sdk/index.js +5 -6
  19. package/package.json +6 -1
  20. package//346/212/200/346/234/257/346/226/271/346/241/210/346/212/245/345/221/212.md +1 -1
  21. package/dist/app-WC2XXGLM.js.map +0 -1
  22. package/dist/chunk-BU64GNXE.js.map +0 -1
  23. package/dist/chunk-DM64TM4Z.js.map +0 -1
  24. package/dist/chunk-JZ322RCJ.js.map +0 -1
  25. package/dist/chunk-M744K7MK.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-XS2JU6S3.js.map +0 -1
  29. package/dist/claude-ink-ZL4UZMFY.js.map +0 -1
  30. package/dist/cli.js.map +0 -1
  31. package/dist/desktop/main.js.map +0 -1
  32. package/dist/desktop/preload.cjs.map +0 -1
  33. package/dist/desktop-renderer/assets/index-C66pDvHs.js.map +0 -1
  34. package/dist/devtools-SXJBSV2N.js.map +0 -1
  35. package/dist/load-WQGNTCHC.js.map +0 -1
  36. package/dist/sdk/index.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from "node:module"; const require = createRequire(import.meta.url);
3
3
  import {
4
4
  statusPresentation
5
- } from "./chunk-DM64TM4Z.js";
5
+ } from "./chunk-KKIBYDJI.js";
6
6
  import {
7
7
  COMMAND_DESCRIPTIONS,
8
8
  MVP_COMMANDS,
@@ -14,8 +14,8 @@ import {
14
14
  modelContentTranscriptText,
15
15
  redactErrorText,
16
16
  transcriptReducer
17
- } from "./chunk-BU64GNXE.js";
18
- import "./chunk-MVIMQEQT.js";
17
+ } from "./chunk-MRISY6KK.js";
18
+ import "./chunk-HFR2WS6T.js";
19
19
  import {
20
20
  Box_default,
21
21
  ClockContext,
@@ -32,11 +32,11 @@ import {
32
32
  useStdout,
33
33
  use_app_default,
34
34
  use_input_default
35
- } from "./chunk-XS2JU6S3.js";
35
+ } from "./chunk-NVLYFU6P.js";
36
36
  import {
37
37
  execFileNoThrow
38
- } from "./chunk-VOCZVFP7.js";
39
- import "./chunk-JZ322RCJ.js";
38
+ } from "./chunk-N2S7USST.js";
39
+ import "./chunk-S32JRDZK.js";
40
40
 
41
41
  // src/ui/app.tsx
42
42
  import { basename as basename3 } from "path";
@@ -3182,4 +3182,3 @@ export {
3182
3182
  submitSafely,
3183
3183
  taskPanelViewportRows
3184
3184
  };
3185
- //# sourceMappingURL=app-WC2XXGLM.js.map
@@ -689,4 +689,3 @@ export {
689
689
  setProjectProviderConfig,
690
690
  redactConfig
691
691
  };
692
- //# sourceMappingURL=chunk-MVIMQEQT.js.map
@@ -121,4 +121,3 @@ export {
121
121
  staticTaskLines,
122
122
  statusPresentation
123
123
  };
124
- //# sourceMappingURL=chunk-DM64TM4Z.js.map
@@ -4,7 +4,7 @@ import {
4
4
  message,
5
5
  redactErrorText,
6
6
  redactSecrets
7
- } from "./chunk-BU64GNXE.js";
7
+ } from "./chunk-MRISY6KK.js";
8
8
 
9
9
  // src/rpc/server.ts
10
10
  import { createInterface } from "readline";
@@ -243,4 +243,3 @@ export {
243
243
  TraceRecordSchema,
244
244
  TraceRecorder
245
245
  };
246
- //# sourceMappingURL=chunk-M744K7MK.js.map
@@ -12,7 +12,7 @@ import {
12
12
  redactConfig,
13
13
  setProjectMcpServerDisabled,
14
14
  updateProtectedFile
15
- } from "./chunk-MVIMQEQT.js";
15
+ } from "./chunk-HFR2WS6T.js";
16
16
  import {
17
17
  AuditLogger,
18
18
  appendUsageLog,
@@ -23,7 +23,7 @@ import {
23
23
  resolveLanguage,
24
24
  setUsageSession,
25
25
  usageLogPath
26
- } from "./chunk-VOCZVFP7.js";
26
+ } from "./chunk-N2S7USST.js";
27
27
 
28
28
  // src/models/types.ts
29
29
  function modelContentText(content) {
@@ -7757,6 +7757,7 @@ var OpenAIModelAdapter = class {
7757
7757
  async *stream(request) {
7758
7758
  const callIds = /* @__PURE__ */ new Map();
7759
7759
  const pendingCalls = /* @__PURE__ */ new Map();
7760
+ const emittedCalls = /* @__PURE__ */ new Set();
7760
7761
  try {
7761
7762
  const body = {
7762
7763
  model: request.model,
@@ -7771,20 +7772,34 @@ var OpenAIModelAdapter = class {
7771
7772
  };
7772
7773
  const stream = this.client.responses.stream(body, { signal: request.signal });
7773
7774
  for await (const event of stream) {
7774
- if ((event.type === "response.output_item.added" || event.type === "response.output_item.done") && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
7775
+ if (event.type === "response.output_item.added" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
7775
7776
  callIds.set(event.output_index, event.item.call_id);
7776
7777
  const pending = pendingCalls.get(event.output_index);
7777
- if (pending) {
7778
+ if (pending && !emittedCalls.has(event.output_index)) {
7778
7779
  yield toolCallEvent(event.item.call_id, pending.name, pending.arguments);
7780
+ emittedCalls.add(event.output_index);
7781
+ pendingCalls.delete(event.output_index);
7782
+ }
7783
+ } else if (event.type === "response.output_item.done" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
7784
+ callIds.set(event.output_index, event.item.call_id);
7785
+ if (!emittedCalls.has(event.output_index)) {
7786
+ const pending = pendingCalls.get(event.output_index);
7787
+ yield toolCallEvent(
7788
+ event.item.call_id,
7789
+ pending?.name ?? event.item.name,
7790
+ pending?.arguments ?? event.item.arguments
7791
+ );
7792
+ emittedCalls.add(event.output_index);
7779
7793
  pendingCalls.delete(event.output_index);
7780
7794
  }
7781
7795
  } else if (event.type === "response.output_text.delta" && event.delta) {
7782
7796
  yield { type: "text", text: event.delta };
7783
7797
  } else if (event.type === "response.function_call_arguments.done" && event.output_index !== void 0 && event.name) {
7784
7798
  const callId = callIds.get(event.output_index);
7785
- if (callId) {
7799
+ if (callId && !emittedCalls.has(event.output_index)) {
7786
7800
  yield toolCallEvent(callId, event.name, event.arguments ?? "");
7787
- } else {
7801
+ emittedCalls.add(event.output_index);
7802
+ } else if (!emittedCalls.has(event.output_index)) {
7788
7803
  pendingCalls.set(event.output_index, {
7789
7804
  name: event.name,
7790
7805
  arguments: event.arguments ?? ""
@@ -10649,19 +10664,20 @@ function createReadTool(workspace, options = {}) {
10649
10664
  if (startLine !== void 0 && endLine !== void 0 && endLine < startLine) {
10650
10665
  throw new Error(`endLine (${endLine}) must not be below startLine (${startLine})`);
10651
10666
  }
10652
- const contents = await readBounded2(path, maxBytes, signal, openFile2);
10667
+ const rangeRequested = startLine !== void 0 || endLine !== void 0;
10668
+ const windowBytes = rangeRequested ? Math.max(maxBytes, Math.min(info.size, MAX_READ_BYTES)) : maxBytes;
10669
+ const contents = await readBounded2(path, windowBytes, signal, openFile2);
10653
10670
  if (isBinary(contents)) throw new Error("Cannot read binary file as text");
10654
- const textEnd = utf8SafeEnd(contents, maxBytes);
10655
- const truncated = contents.length > maxBytes;
10671
+ const textEnd = utf8SafeEnd(contents, windowBytes);
10672
+ const truncated = contents.length > windowBytes;
10656
10673
  const text = contents.subarray(0, textEnd).toString("utf8").replaceAll("\r\n", "\n");
10657
10674
  const lines = text.split("\n");
10658
10675
  if (lines.at(-1) === "") lines.pop();
10659
10676
  const availableLines = lines.length;
10660
- const rangeRequested = startLine !== void 0 || endLine !== void 0;
10661
10677
  const start = startLine ?? 1;
10662
10678
  const end = Math.min(endLine ?? availableLines, availableLines);
10663
10679
  if (rangeRequested && start > availableLines) {
10664
- 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"}`);
10680
+ 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"}`);
10665
10681
  }
10666
10682
  if (rangeRequested && end < start) {
10667
10683
  throw new Error(`endLine (${endLine}) must not be below startLine (${start})`);
@@ -10677,13 +10693,13 @@ function createReadTool(workspace, options = {}) {
10677
10693
  record.ranges = mergeRange(record.ranges, start, end);
10678
10694
  }
10679
10695
  if (rangeRequested) {
10680
- const header = `[Lines ${start}-${end} of ${availableLines}${truncated ? ` visible in this read (truncated at ${maxBytes} bytes)` : ""}]`;
10696
+ const header = `[Lines ${start}-${end} of ${availableLines}${truncated ? ` visible in this read (truncated at ${windowBytes} bytes)` : ""}]`;
10681
10697
  return `${header}
10682
10698
 
10683
10699
  ${lines.slice(start - 1, end).join("\n")}`;
10684
10700
  }
10685
10701
  if (truncated) {
10686
- return `[Truncated to ${maxBytes} bytes. File is ${info.size} bytes total. Request a higher maxBytes or read a specific range with startLine/endLine.]
10702
+ return `[Truncated to ${windowBytes} bytes. File is ${info.size} bytes total. Request a higher maxBytes or read a specific range with startLine/endLine.]
10687
10703
 
10688
10704
  ${text}`;
10689
10705
  }
@@ -15768,4 +15784,3 @@ export {
15768
15784
  createExecutionEnvironment,
15769
15785
  createProductionRuntime
15770
15786
  };
15771
- //# sourceMappingURL=chunk-BU64GNXE.js.map
@@ -150,4 +150,3 @@ export {
150
150
  resolveLanguage,
151
151
  languageInstruction
152
152
  };
153
- //# sourceMappingURL=chunk-VOCZVFP7.js.map
@@ -5,12 +5,12 @@ import {
5
5
  getGraphemeSegmenter,
6
6
  isEnvTruthy,
7
7
  logError
8
- } from "./chunk-VOCZVFP7.js";
8
+ } from "./chunk-N2S7USST.js";
9
9
  import {
10
10
  __commonJS,
11
11
  __require,
12
12
  __toESM
13
- } from "./chunk-JZ322RCJ.js";
13
+ } from "./chunk-S32JRDZK.js";
14
14
 
15
15
  // node_modules/scheduler/cjs/scheduler.production.js
16
16
  var require_scheduler_production = __commonJS({
@@ -28001,7 +28001,7 @@ var styles_default = styles2;
28001
28001
  // src/claude-ink/reconciler.ts
28002
28002
  if (process.env.NODE_ENV === "development") {
28003
28003
  try {
28004
- void import("./devtools-SXJBSV2N.js");
28004
+ void import("./devtools-4QTPKBKK.js");
28005
28005
  } catch (error) {
28006
28006
  if (error.code === "ERR_MODULE_NOT_FOUND") {
28007
28007
  console.warn(
@@ -35554,4 +35554,3 @@ react-reconciler/cjs/react-reconciler-constants.development.js:
35554
35554
  * LICENSE file in the root directory of this source tree.
35555
35555
  *)
35556
35556
  */
35557
- //# sourceMappingURL=chunk-XS2JU6S3.js.map
@@ -37,4 +37,3 @@ export {
37
37
  __commonJS,
38
38
  __toESM
39
39
  };
40
- //# sourceMappingURL=chunk-JZ322RCJ.js.map
@@ -10,9 +10,9 @@ import {
10
10
  useStdout,
11
11
  use_app_default,
12
12
  use_input_default
13
- } from "./chunk-XS2JU6S3.js";
14
- import "./chunk-VOCZVFP7.js";
15
- import "./chunk-JZ322RCJ.js";
13
+ } from "./chunk-NVLYFU6P.js";
14
+ import "./chunk-N2S7USST.js";
15
+ import "./chunk-S32JRDZK.js";
16
16
  export {
17
17
  AlternateScreen,
18
18
  Box_default as Box,
@@ -24,4 +24,3 @@ export {
24
24
  use_input_default as useInput,
25
25
  useStdout
26
26
  };
27
- //# sourceMappingURL=claude-ink-ZL4UZMFY.js.map
package/dist/cli.js CHANGED
@@ -3,10 +3,10 @@ import { createRequire } from "node:module"; const require = createRequire(impor
3
3
  import {
4
4
  FlavorRpcServer,
5
5
  TraceRecorder
6
- } from "./chunk-M744K7MK.js";
6
+ } from "./chunk-L5A2NDMT.js";
7
7
  import {
8
8
  staticTaskLines
9
- } from "./chunk-DM64TM4Z.js";
9
+ } from "./chunk-KKIBYDJI.js";
10
10
  import {
11
11
  DEFAULT_MAX_OUTPUT_BYTES,
12
12
  MEMORY_TYPES,
@@ -20,7 +20,7 @@ import {
20
20
  message,
21
21
  packageVersion,
22
22
  redactErrorText
23
- } from "./chunk-BU64GNXE.js";
23
+ } from "./chunk-MRISY6KK.js";
24
24
  import {
25
25
  McpServerConfigSchema,
26
26
  McpServerNameSchema,
@@ -29,9 +29,9 @@ import {
29
29
  readRecoverableFile,
30
30
  setProjectSkillDisabled,
31
31
  updateProtectedFile
32
- } from "./chunk-MVIMQEQT.js";
33
- import "./chunk-VOCZVFP7.js";
34
- import "./chunk-JZ322RCJ.js";
32
+ } from "./chunk-HFR2WS6T.js";
33
+ import "./chunk-N2S7USST.js";
34
+ import "./chunk-S32JRDZK.js";
35
35
 
36
36
  // src/cli.tsx
37
37
  import { realpathSync } from "fs";
@@ -669,7 +669,7 @@ async function runEvaluationFile(path, outputPath) {
669
669
  })),
670
670
  ...parsed.maxTokens === void 0 ? {} : { maxTokens: parsed.maxTokens }
671
671
  };
672
- const configured = await import("./load-WQGNTCHC.js").then(({ loadConfig: loadConfig2 }) => loadConfig2({ cwd: workspace, home: process.env.USERPROFILE ?? process.env.HOME ?? workspace }));
672
+ const configured = await import("./load-XC5JYYBQ.js").then(({ loadConfig: loadConfig2 }) => loadConfig2({ cwd: workspace, home: process.env.USERPROFILE ?? process.env.HOME ?? workspace }));
673
673
  const environment = createExecutionEnvironment(workspace, configured.config.execution) ?? new LocalExecutionEnvironment();
674
674
  let report;
675
675
  try {
@@ -769,9 +769,9 @@ function createProgram() {
769
769
  }
770
770
  setInteractiveProcessTitle();
771
771
  const [{ render, AlternateScreen }, { createElement }, { App }] = await Promise.all([
772
- import("./claude-ink-ZL4UZMFY.js"),
772
+ import("./claude-ink-WPWPEL5A.js"),
773
773
  import("react"),
774
- import("./app-WC2XXGLM.js")
774
+ import("./app-N3655H2E.js")
775
775
  ]);
776
776
  const instance = await render(createElement(
777
777
  AlternateScreen,
@@ -912,4 +912,3 @@ export {
912
912
  runRpcMode,
913
913
  setInteractiveProcessTitle
914
914
  };
915
- //# sourceMappingURL=cli.js.map
@@ -6762,6 +6762,7 @@ var OpenAIModelAdapter = class {
6762
6762
  async *stream(request) {
6763
6763
  const callIds = /* @__PURE__ */ new Map();
6764
6764
  const pendingCalls = /* @__PURE__ */ new Map();
6765
+ const emittedCalls = /* @__PURE__ */ new Set();
6765
6766
  try {
6766
6767
  const body = {
6767
6768
  model: request.model,
@@ -6776,20 +6777,34 @@ var OpenAIModelAdapter = class {
6776
6777
  };
6777
6778
  const stream = this.client.responses.stream(body, { signal: request.signal });
6778
6779
  for await (const event of stream) {
6779
- if ((event.type === "response.output_item.added" || event.type === "response.output_item.done") && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
6780
+ if (event.type === "response.output_item.added" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
6780
6781
  callIds.set(event.output_index, event.item.call_id);
6781
6782
  const pending2 = pendingCalls.get(event.output_index);
6782
- if (pending2) {
6783
+ if (pending2 && !emittedCalls.has(event.output_index)) {
6783
6784
  yield toolCallEvent(event.item.call_id, pending2.name, pending2.arguments);
6785
+ emittedCalls.add(event.output_index);
6786
+ pendingCalls.delete(event.output_index);
6787
+ }
6788
+ } else if (event.type === "response.output_item.done" && event.item?.type === "function_call" && event.output_index !== void 0 && event.item.call_id) {
6789
+ callIds.set(event.output_index, event.item.call_id);
6790
+ if (!emittedCalls.has(event.output_index)) {
6791
+ const pending2 = pendingCalls.get(event.output_index);
6792
+ yield toolCallEvent(
6793
+ event.item.call_id,
6794
+ pending2?.name ?? event.item.name,
6795
+ pending2?.arguments ?? event.item.arguments
6796
+ );
6797
+ emittedCalls.add(event.output_index);
6784
6798
  pendingCalls.delete(event.output_index);
6785
6799
  }
6786
6800
  } else if (event.type === "response.output_text.delta" && event.delta) {
6787
6801
  yield { type: "text", text: event.delta };
6788
6802
  } else if (event.type === "response.function_call_arguments.done" && event.output_index !== void 0 && event.name) {
6789
6803
  const callId = callIds.get(event.output_index);
6790
- if (callId) {
6804
+ if (callId && !emittedCalls.has(event.output_index)) {
6791
6805
  yield toolCallEvent(callId, event.name, event.arguments ?? "");
6792
- } else {
6806
+ emittedCalls.add(event.output_index);
6807
+ } else if (!emittedCalls.has(event.output_index)) {
6793
6808
  pendingCalls.set(event.output_index, {
6794
6809
  name: event.name,
6795
6810
  arguments: event.arguments ?? ""
@@ -10415,19 +10430,20 @@ function createReadTool(workspace, options = {}) {
10415
10430
  if (startLine !== void 0 && endLine !== void 0 && endLine < startLine) {
10416
10431
  throw new Error(`endLine (${endLine}) must not be below startLine (${startLine})`);
10417
10432
  }
10418
- const contents = await readBounded2(path, maxBytes, signal, openFile2);
10433
+ const rangeRequested = startLine !== void 0 || endLine !== void 0;
10434
+ const windowBytes = rangeRequested ? Math.max(maxBytes, Math.min(info.size, MAX_READ_BYTES)) : maxBytes;
10435
+ const contents = await readBounded2(path, windowBytes, signal, openFile2);
10419
10436
  if (isBinary(contents)) throw new Error("Cannot read binary file as text");
10420
- const textEnd = utf8SafeEnd(contents, maxBytes);
10421
- const truncated = contents.length > maxBytes;
10437
+ const textEnd = utf8SafeEnd(contents, windowBytes);
10438
+ const truncated = contents.length > windowBytes;
10422
10439
  const text = contents.subarray(0, textEnd).toString("utf8").replaceAll("\r\n", "\n");
10423
10440
  const lines = text.split("\n");
10424
10441
  if (lines.at(-1) === "") lines.pop();
10425
10442
  const availableLines = lines.length;
10426
- const rangeRequested = startLine !== void 0 || endLine !== void 0;
10427
10443
  const start = startLine ?? 1;
10428
10444
  const end = Math.min(endLine ?? availableLines, availableLines);
10429
10445
  if (rangeRequested && start > availableLines) {
10430
- 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"}`);
10446
+ 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"}`);
10431
10447
  }
10432
10448
  if (rangeRequested && end < start) {
10433
10449
  throw new Error(`endLine (${endLine}) must not be below startLine (${start})`);
@@ -10443,13 +10459,13 @@ function createReadTool(workspace, options = {}) {
10443
10459
  record.ranges = mergeRange(record.ranges, start, end);
10444
10460
  }
10445
10461
  if (rangeRequested) {
10446
- const header = `[Lines ${start}-${end} of ${availableLines}${truncated ? ` visible in this read (truncated at ${maxBytes} bytes)` : ""}]`;
10462
+ const header = `[Lines ${start}-${end} of ${availableLines}${truncated ? ` visible in this read (truncated at ${windowBytes} bytes)` : ""}]`;
10447
10463
  return `${header}
10448
10464
 
10449
10465
  ${lines.slice(start - 1, end).join("\n")}`;
10450
10466
  }
10451
10467
  if (truncated) {
10452
- return `[Truncated to ${maxBytes} bytes. File is ${info.size} bytes total. Request a higher maxBytes or read a specific range with startLine/endLine.]
10468
+ return `[Truncated to ${windowBytes} bytes. File is ${info.size} bytes total. Request a higher maxBytes or read a specific range with startLine/endLine.]
10453
10469
 
10454
10470
  ${text}`;
10455
10471
  }
@@ -17775,4 +17791,3 @@ app.on("before-quit", () => {
17775
17791
  app.on("window-all-closed", () => {
17776
17792
  if (process.platform !== "darwin") app.quit();
17777
17793
  });
17778
- //# 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-M744K7MK.js";
7
+ } from "../chunk-L5A2NDMT.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-BU64GNXE.js";
17
- import "../chunk-MVIMQEQT.js";
18
- import "../chunk-VOCZVFP7.js";
19
- import "../chunk-JZ322RCJ.js";
16
+ } from "../chunk-MRISY6KK.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.2",
3
+ "version": "1.2.4",
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,6 +19,7 @@
16
19
  },
17
20
  "files": [
18
21
  "dist/",
22
+ "!dist/**/*.map",
19
23
  "README.md",
20
24
  "技术方案报告.md",
21
25
  "LICENSE"
@@ -55,6 +59,7 @@
55
59
  },
56
60
  "files": [
57
61
  "dist/**/*",
62
+ "!dist/**/*.map",
58
63
  "assets/icon.png",
59
64
  "package.json",
60
65
  "README.md",
@@ -1,6 +1,6 @@
1
1
  # flavor-code 技术方案报告
2
2
 
3
- > 版本:1.2.1 | 语言:TypeScript | 运行时:Node.js ≥20 | 包管理器:npm
3
+ > 版本:1.2.4 | 语言:TypeScript | 运行时:Node.js ≥20 | 包管理器:npm
4
4
 
5
5
  ---
6
6