@zhongqian97-code/ecode 0.5.58 → 0.5.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,7 +4,7 @@ import {
4
4
  createSessionMetadata,
5
5
  updateSessionMetadata,
6
6
  writeSessionMetadata
7
- } from "./chunk-SIQQG6FT.js";
7
+ } from "./chunk-LODP7T4D.js";
8
8
 
9
9
  // src/skills/loader.ts
10
10
  import { readFile, readdir, stat } from "fs/promises";
@@ -134,6 +134,33 @@ function saveConfig(partial) {
134
134
 
135
135
  // src/providers/openai.ts
136
136
  import OpenAI from "openai";
137
+ function trimToFirstJson(s) {
138
+ try {
139
+ JSON.parse(s);
140
+ return s;
141
+ } catch {
142
+ }
143
+ let depth = 0, inStr = false, esc = false;
144
+ for (let i = 0; i < s.length; i++) {
145
+ const c = s[i];
146
+ if (esc) {
147
+ esc = false;
148
+ continue;
149
+ }
150
+ if (c === "\\" && inStr) {
151
+ esc = true;
152
+ continue;
153
+ }
154
+ if (c === '"') {
155
+ inStr = !inStr;
156
+ continue;
157
+ }
158
+ if (inStr) continue;
159
+ if (c === "{" || c === "[") depth++;
160
+ else if ((c === "}" || c === "]") && --depth === 0) return s.slice(0, i + 1);
161
+ }
162
+ return s;
163
+ }
137
164
  function createOpenAIProvider(profile) {
138
165
  const THINK_END = "</think>";
139
166
  const openai = new OpenAI({
@@ -302,7 +329,10 @@ function createOpenAIProvider(profile) {
302
329
  finishReason: choice.finish_reason,
303
330
  // tcAccumulator 为空说明本轮没有工具调用,传 undefined 而非空数组,
304
331
  // 让调用方用 if (chunk.toolCalls) 做简洁判断
305
- toolCalls: tcAccumulator.size > 0 ? Array.from(tcAccumulator.values()) : void 0,
332
+ toolCalls: tcAccumulator.size > 0 ? Array.from(tcAccumulator.values()).map((tc) => ({
333
+ ...tc,
334
+ arguments: trimToFirstJson(tc.arguments)
335
+ })) : void 0,
306
336
  reasoning: reasoningAccumulator || void 0,
307
337
  // reasoningDetails 仅在流中出现过结构化推理时返回(MiniMax 兼容)
308
338
  reasoningDetails: reasoningDetailsAcc.size > 0 ? Array.from(reasoningDetailsAcc.values()) : void 0,
@@ -3,7 +3,7 @@ const _ew=process.emitWarning.bind(process);process.emitWarning=function(w,...a)
3
3
  import {
4
4
  findSession,
5
5
  listSessions
6
- } from "./chunk-SIQQG6FT.js";
6
+ } from "./chunk-LODP7T4D.js";
7
7
 
8
8
  // src/sessions/command.ts
9
9
  import * as path from "path";
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  cmdSessionsInspect,
6
6
  cmdSessionsList,
7
7
  cmdSessionsReplay
8
- } from "./chunk-N3IDMSG5.js";
8
+ } from "./chunk-ZNCND354.js";
9
9
  import {
10
10
  APPLY_PATCH_TOOL,
11
11
  BASH_TOOL,
@@ -33,7 +33,7 @@ import {
33
33
  todo,
34
34
  webFetch,
35
35
  writeFile
36
- } from "./chunk-V3JQ7HAU.js";
36
+ } from "./chunk-HC62ZZI6.js";
37
37
  import {
38
38
  createProvider,
39
39
  createSessionMetadata,
@@ -42,7 +42,7 @@ import {
42
42
  resolveActiveProfile,
43
43
  updateSessionMetadata,
44
44
  writeSessionMetadata
45
- } from "./chunk-SIQQG6FT.js";
45
+ } from "./chunk-LODP7T4D.js";
46
46
 
47
47
  // src/index.ts
48
48
  import { createRequire } from "module";
@@ -197,7 +197,12 @@ async function runPipe(prompt, llm, out = process.stdout, systemPrompt) {
197
197
  });
198
198
  for (const tc of toolCalls) {
199
199
  emit(out, { type: "tool_call", id: tc.id, name: tc.name, arguments: tc.arguments });
200
- const content = await executeToolCall(tc.name, tc.arguments);
200
+ let content;
201
+ try {
202
+ content = await executeToolCall(tc.name, tc.arguments);
203
+ } catch (err) {
204
+ content = `Tool error: ${String(err)}`;
205
+ }
201
206
  emit(out, { type: "tool_result", toolCallId: tc.id, name: tc.name, content });
202
207
  messages.push({ role: "tool", tool_call_id: tc.id, content });
203
208
  }
@@ -814,7 +819,7 @@ if (rawArgs[0] === "web") {
814
819
  webAutoApprove = true;
815
820
  }
816
821
  }
817
- const { buildServer, generateAccessToken } = await import("./web-3CS3TO2E.js");
822
+ const { buildServer, generateAccessToken } = await import("./web-N7JFJIBC.js");
818
823
  const token = finalConfig.webToken ?? generateAccessToken();
819
824
  const manager = new SessionManager(finalConfig);
820
825
  const __webDirname = dirname(fileURLToPath(import.meta.url));
@@ -898,7 +903,7 @@ Press Ctrl+C to stop.
898
903
  process.exit(0);
899
904
  }
900
905
  if (process.stdout.isTTY) {
901
- process.stdout.write("\x1B[?1049h");
906
+ process.stdout.write("\x1B[?1049h\x1B[H");
902
907
  const exitAltScreen = () => process.stdout.write("\x1B[?1049l");
903
908
  process.on("exit", exitAltScreen);
904
909
  process.on("SIGINT", () => {
@@ -923,7 +928,7 @@ Node.js 16/18 \u8BF7\u4F7F\u7528 --web \u6216 --pipe \u6A21\u5F0F\u3002
923
928
  );
924
929
  process.exit(1);
925
930
  }
926
- const { App, React, render, createStdinFilter } = await import("./ui-STSJVDXD.js");
931
+ const { App, React, render, createStdinFilter } = await import("./ui-3HB6NDEE.js");
927
932
  const stdinFilter = process.stdin.isTTY ? createStdinFilter(process.stdin) : process.stdin;
928
933
  render(
929
934
  React.createElement(App, { config: finalConfig, version: VERSION, autoMode, registry, trustedSkillDirs, initialMessages, stdinFilter }),
@@ -24,7 +24,7 @@ import {
24
24
  todo,
25
25
  webFetch,
26
26
  writeFile
27
- } from "./chunk-V3JQ7HAU.js";
27
+ } from "./chunk-HC62ZZI6.js";
28
28
  import {
29
29
  handleSkillInput,
30
30
  loadJobs,
@@ -39,7 +39,7 @@ import {
39
39
  resolveActiveProfile,
40
40
  updateSessionMetadata,
41
41
  writeSessionMetadata
42
- } from "./chunk-SIQQG6FT.js";
42
+ } from "./chunk-LODP7T4D.js";
43
43
 
44
44
  // src/ui/index.ts
45
45
  import { default as default2 } from "react";
@@ -403,6 +403,24 @@ function ConversationHistory({
403
403
  // src/ui/Input.tsx
404
404
  import { useState as useState2, useEffect as useEffect2, useRef, forwardRef, useImperativeHandle } from "react";
405
405
  import { Box as Box3, Text as Text3, useInput } from "ink";
406
+
407
+ // src/ui/inputClick.ts
408
+ var INPUT_PREFIX_WIDTH = 2;
409
+ function clickToCursor(value, localRow, localCol) {
410
+ if (value.length === 0) return 0;
411
+ const lines = value.split("\n");
412
+ if (localRow < 0) return 0;
413
+ if (localRow >= lines.length) return value.length;
414
+ let pos = 0;
415
+ for (let i = 0; i < localRow; i++) {
416
+ pos += lines[i].length + 1;
417
+ }
418
+ const lineCol = Math.max(0, localCol - INPUT_PREFIX_WIDTH);
419
+ pos += Math.min(lineCol, lines[localRow].length);
420
+ return pos;
421
+ }
422
+
423
+ // src/ui/Input.tsx
406
424
  import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
407
425
  var CURSOR_CHAR = "\u258C";
408
426
  var BLINK_INTERVAL_MS = 530;
@@ -430,11 +448,14 @@ function wordForward(s, pos) {
430
448
  var Input = forwardRef(function Input2({ isActive, onSubmit, onChange, placeholder }, ref) {
431
449
  const [value, setValue] = useState2("");
432
450
  const [cursorPos, setCursorPos] = useState2(0);
451
+ const [inputSel, setInputSel] = useState2(null);
433
452
  const [cursorVisible, setCursorVisible] = useState2(true);
434
453
  const valueRef = useRef(value);
435
454
  valueRef.current = value;
436
455
  const cursorPosRef = useRef(cursorPos);
437
456
  cursorPosRef.current = cursorPos;
457
+ const inputSelRef = useRef(inputSel);
458
+ inputSelRef.current = inputSel;
438
459
  const onChangeRef = useRef(onChange);
439
460
  onChangeRef.current = onChange;
440
461
  const onSubmitRef = useRef(onSubmit);
@@ -446,7 +467,42 @@ var Input = forwardRef(function Input2({ isActive, onSubmit, onChange, placehold
446
467
  cursorPosRef.current = text.length;
447
468
  setValue(text);
448
469
  setCursorPos(text.length);
470
+ inputSelRef.current = null;
471
+ setInputSel(null);
449
472
  (_a = onChangeRef.current) == null ? void 0 : _a.call(onChangeRef, text);
473
+ },
474
+ getValue() {
475
+ return valueRef.current;
476
+ },
477
+ setCursorByClick(line, col) {
478
+ const pos = clickToCursor(valueRef.current, line, col);
479
+ cursorPosRef.current = pos;
480
+ setCursorPos(pos);
481
+ },
482
+ startInputSelection(line, col) {
483
+ const pos = clickToCursor(valueRef.current, line, col);
484
+ const next = { anchor: pos, focus: pos };
485
+ inputSelRef.current = next;
486
+ setInputSel(next);
487
+ },
488
+ extendInputSelection(line, col) {
489
+ const cur = inputSelRef.current;
490
+ if (!cur) return;
491
+ const pos = clickToCursor(valueRef.current, line, col);
492
+ const next = { anchor: cur.anchor, focus: pos };
493
+ inputSelRef.current = next;
494
+ setInputSel(next);
495
+ },
496
+ getInputSelectionText() {
497
+ const cur = inputSelRef.current;
498
+ if (!cur || cur.anchor === cur.focus) return "";
499
+ const s = Math.min(cur.anchor, cur.focus);
500
+ const e = Math.max(cur.anchor, cur.focus);
501
+ return valueRef.current.slice(s, e);
502
+ },
503
+ clearInputSelection() {
504
+ inputSelRef.current = null;
505
+ setInputSel(null);
450
506
  }
451
507
  }));
452
508
  useEffect2(() => {
@@ -474,6 +530,10 @@ var Input = forwardRef(function Input2({ isActive, onSubmit, onChange, placehold
474
530
  var _a, _b, _c, _d, _e, _f, _g, _h;
475
531
  const v = valueRef.current;
476
532
  const pos = cursorPosRef.current;
533
+ if (inputSelRef.current) {
534
+ inputSelRef.current = null;
535
+ setInputSel(null);
536
+ }
477
537
  if (key.return && key.shift) {
478
538
  const newValue = v.slice(0, pos) + "\n" + v.slice(pos);
479
539
  setValueSync(newValue);
@@ -601,9 +661,34 @@ var Input = forwardRef(function Input2({ isActive, onSubmit, onChange, placehold
601
661
  }
602
662
  remaining -= lineLen + 1;
603
663
  }
664
+ const selMin = inputSel ? Math.min(inputSel.anchor, inputSel.focus) : null;
665
+ const selMax = inputSel ? Math.max(inputSel.anchor, inputSel.focus) : null;
666
+ const hasSel = selMin !== null && selMax !== null && selMin !== selMax;
604
667
  return /* @__PURE__ */ jsx3(Box3, { flexDirection: "column", children: lines.map((line, idx) => {
605
668
  const prefix = idx === 0 ? "> " : " ";
606
- const showCursor = isActive && cursorVisible && idx === cursorLine;
669
+ const showCursor = isActive && cursorVisible && idx === cursorLine && !hasSel;
670
+ if (hasSel) {
671
+ let lineStartAbs = 0;
672
+ for (let i = 0; i < idx; i++) lineStartAbs += lines[i].length + 1;
673
+ const lineEndAbs = lineStartAbs + line.length;
674
+ const iStart = Math.max(lineStartAbs, selMin);
675
+ const iEnd = Math.min(lineEndAbs, selMax);
676
+ if (iStart >= iEnd) {
677
+ return /* @__PURE__ */ jsxs3(Box3, { children: [
678
+ /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: prefix }),
679
+ /* @__PURE__ */ jsx3(Text3, { children: line })
680
+ ] }, idx);
681
+ }
682
+ const before2 = line.slice(0, iStart - lineStartAbs);
683
+ const selChunk = line.slice(iStart - lineStartAbs, iEnd - lineStartAbs);
684
+ const after2 = line.slice(iEnd - lineStartAbs);
685
+ return /* @__PURE__ */ jsxs3(Box3, { children: [
686
+ /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: prefix }),
687
+ before2 && /* @__PURE__ */ jsx3(Text3, { children: before2 }),
688
+ /* @__PURE__ */ jsx3(Text3, { inverse: true, children: selChunk || " " }),
689
+ after2 && /* @__PURE__ */ jsx3(Text3, { children: after2 })
690
+ ] }, idx);
691
+ }
607
692
  if (!showCursor) {
608
693
  return /* @__PURE__ */ jsxs3(Box3, { children: [
609
694
  /* @__PURE__ */ jsx3(Text3, { color: "cyan", children: prefix }),
@@ -2551,6 +2636,7 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2551
2636
  useEffect3(() => {
2552
2637
  if (!stdinFilter) return;
2553
2638
  const onMouse = (e) => {
2639
+ var _a, _b, _c, _d, _e;
2554
2640
  if (e.kind === "scroll") {
2555
2641
  const step = Math.max(1, Math.floor(historyMaxHeightRef.current / 2));
2556
2642
  if (e.direction === "up") {
@@ -2560,6 +2646,27 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2560
2646
  }
2561
2647
  return;
2562
2648
  }
2649
+ const tRows = terminalRowsRef.current;
2650
+ const inRows = inputRowsRef.current;
2651
+ const inputStartRow = tRows - inRows;
2652
+ if (e.row >= inputStartRow && e.row <= tRows - 1) {
2653
+ const localRow = e.row - inputStartRow;
2654
+ if (e.type === "leftDown") {
2655
+ (_a = inputRef.current) == null ? void 0 : _a.setCursorByClick(localRow, e.col);
2656
+ (_b = inputRef.current) == null ? void 0 : _b.startInputSelection(localRow, e.col);
2657
+ } else if (e.type === "leftDrag") {
2658
+ (_c = inputRef.current) == null ? void 0 : _c.extendInputSelection(localRow, e.col);
2659
+ } else if (e.type === "leftUp") {
2660
+ const text = ((_d = inputRef.current) == null ? void 0 : _d.getInputSelectionText()) ?? "";
2661
+ if (text.length > 0 && stdout) {
2662
+ const b64 = Buffer.from(text, "utf8").toString("base64");
2663
+ stdout.write(`\x1B]52;c;${b64}\x07`);
2664
+ } else {
2665
+ (_e = inputRef.current) == null ? void 0 : _e.clearInputSelection();
2666
+ }
2667
+ }
2668
+ return;
2669
+ }
2563
2670
  const window = computeVisibleWindow(
2564
2671
  totalLinesRef.current,
2565
2672
  scrollOffsetRef.current,
@@ -2567,8 +2674,8 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2567
2674
  );
2568
2675
  const lineIdx = mouseRowToLineIndex({
2569
2676
  mouseRow: e.row,
2570
- terminalRows: terminalRowsRef.current,
2571
- inputRows: inputRowsRef.current,
2677
+ terminalRows: tRows,
2678
+ inputRows: inRows,
2572
2679
  skillAcRows: skillAcRowsRef.current,
2573
2680
  fileAcRows: fileAcRowsRef.current,
2574
2681
  selectedItemsRows: selectedItemsRowsRef.current,
@@ -2614,7 +2721,7 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2614
2721
  };
2615
2722
  }, [fileAcState.query]);
2616
2723
  useInput2((input, key) => {
2617
- var _a, _b, _c, _d, _e;
2724
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2618
2725
  if (key.escape && status === "thinking" && abortControllerRef.current) {
2619
2726
  abortControllerRef.current.abort();
2620
2727
  return;
@@ -2688,13 +2795,38 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2688
2795
  setScrollOffset((prev) => Math.min(prev + scrollStep, Math.max(0, totalLines - 1)));
2689
2796
  return;
2690
2797
  }
2798
+ const currentInput = ((_c = inputRef.current) == null ? void 0 : _c.getValue()) ?? "";
2799
+ if (currentInput === "" && key.upArrow) {
2800
+ const history = inputHistoryRef.current;
2801
+ const newIndex = Math.min(historyIndexRef.current + 1, history.length - 1);
2802
+ if (newIndex >= 0 && newIndex < history.length) {
2803
+ historyIndexRef.current = newIndex;
2804
+ isNavigatingHistoryRef.current = true;
2805
+ (_d = inputRef.current) == null ? void 0 : _d.fill(history[newIndex]);
2806
+ }
2807
+ return;
2808
+ }
2809
+ if (currentInput === "" && key.downArrow) {
2810
+ const history = inputHistoryRef.current;
2811
+ if (historyIndexRef.current > 0) {
2812
+ const newIndex = historyIndexRef.current - 1;
2813
+ historyIndexRef.current = newIndex;
2814
+ isNavigatingHistoryRef.current = true;
2815
+ (_e = inputRef.current) == null ? void 0 : _e.fill(history[newIndex]);
2816
+ } else if (historyIndexRef.current === 0) {
2817
+ historyIndexRef.current = -1;
2818
+ isNavigatingHistoryRef.current = true;
2819
+ (_f = inputRef.current) == null ? void 0 : _f.fill("");
2820
+ }
2821
+ return;
2822
+ }
2691
2823
  if (key.ctrl && input === "p") {
2692
2824
  const history = inputHistoryRef.current;
2693
2825
  const newIndex = Math.min(historyIndexRef.current + 1, history.length - 1);
2694
2826
  if (newIndex >= 0 && newIndex < history.length) {
2695
2827
  historyIndexRef.current = newIndex;
2696
2828
  isNavigatingHistoryRef.current = true;
2697
- (_c = inputRef.current) == null ? void 0 : _c.fill(history[newIndex]);
2829
+ (_g = inputRef.current) == null ? void 0 : _g.fill(history[newIndex]);
2698
2830
  }
2699
2831
  return;
2700
2832
  }
@@ -2704,11 +2836,11 @@ function App({ config, version, autoMode = false, registry, trustedSkillDirs = [
2704
2836
  const newIndex = historyIndexRef.current - 1;
2705
2837
  historyIndexRef.current = newIndex;
2706
2838
  isNavigatingHistoryRef.current = true;
2707
- (_d = inputRef.current) == null ? void 0 : _d.fill(history[newIndex]);
2839
+ (_h = inputRef.current) == null ? void 0 : _h.fill(history[newIndex]);
2708
2840
  } else if (historyIndexRef.current === 0) {
2709
2841
  historyIndexRef.current = -1;
2710
2842
  isNavigatingHistoryRef.current = true;
2711
- (_e = inputRef.current) == null ? void 0 : _e.fill("");
2843
+ (_i = inputRef.current) == null ? void 0 : _i.fill("");
2712
2844
  }
2713
2845
  return;
2714
2846
  }
@@ -3,7 +3,7 @@ const _ew=process.emitWarning.bind(process);process.emitWarning=function(w,...a)
3
3
  import {
4
4
  cmdSessionsFork,
5
5
  cmdSessionsReplay
6
- } from "./chunk-N3IDMSG5.js";
6
+ } from "./chunk-ZNCND354.js";
7
7
  import {
8
8
  handleSkillInput,
9
9
  loadJobs,
@@ -17,7 +17,7 @@ import {
17
17
  loadMessagesFromJsonl,
18
18
  resolveActiveProfile,
19
19
  saveConfig
20
- } from "./chunk-SIQQG6FT.js";
20
+ } from "./chunk-LODP7T4D.js";
21
21
 
22
22
  // src/web/server.ts
23
23
  import Fastify from "fastify";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhongqian97-code/ecode",
3
- "version": "0.5.58",
3
+ "version": "0.5.60",
4
4
  "description": "A minimal Claude Code clone with REPL interface and bash tool calling",
5
5
  "type": "module",
6
6
  "author": "zhongqian97-code",