@zhongqian97-code/ecode 0.5.65 → 0.5.67

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.
@@ -815,9 +815,9 @@ function createLogger(logDir, sessionStart) {
815
815
  // src/tools/bash.ts
816
816
  import { exec } from "child_process";
817
817
  var DEFAULT_TIMEOUT_MS = 3e4;
818
- function executeBash(cmd, timeoutMs = DEFAULT_TIMEOUT_MS) {
818
+ function executeBash(cmd, timeoutMs = DEFAULT_TIMEOUT_MS, cwd) {
819
819
  return new Promise((resolve4) => {
820
- exec(cmd, { timeout: timeoutMs }, (err, stdout, stderr) => {
820
+ exec(cmd, { timeout: timeoutMs, cwd }, (err, stdout, stderr) => {
821
821
  if (err) {
822
822
  const exitCode = err.code ?? 1;
823
823
  resolve4({ stdout: stdout ?? "", stderr: stderr ?? "", exitCode });
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ import {
34
34
  todo,
35
35
  webFetch,
36
36
  writeFile
37
- } from "./chunk-ZLF4HLQ7.js";
37
+ } from "./chunk-WHVNMO5M.js";
38
38
  import {
39
39
  createProvider,
40
40
  createSessionMetadata,
@@ -47,7 +47,7 @@ import {
47
47
 
48
48
  // src/index.ts
49
49
  import { createRequire } from "module";
50
- import { resolve, dirname } from "path";
50
+ import { resolve as resolve2, dirname } from "path";
51
51
  import { fileURLToPath } from "url";
52
52
  import { readFileSync } from "fs";
53
53
 
@@ -211,19 +211,20 @@ async function runPipe(prompt, llm, out = process.stdout, systemPrompt) {
211
211
  }
212
212
  }
213
213
  function readStdin() {
214
- return new Promise((resolve2, reject) => {
214
+ return new Promise((resolve3, reject) => {
215
215
  let data = "";
216
216
  process.stdin.setEncoding("utf-8");
217
217
  process.stdin.on("data", (chunk) => {
218
218
  data += chunk;
219
219
  });
220
- process.stdin.on("end", () => resolve2(data.trim()));
220
+ process.stdin.on("end", () => resolve3(data.trim()));
221
221
  process.stdin.on("error", reject);
222
222
  });
223
223
  }
224
224
 
225
225
  // src/runtime/session.ts
226
226
  import { randomUUID as randomUUID2 } from "crypto";
227
+ import * as path from "path";
227
228
 
228
229
  // src/runtime/events.ts
229
230
  var EventBus = class {
@@ -264,10 +265,10 @@ var ApprovalQueue = class {
264
265
  */
265
266
  request(kind, prompt) {
266
267
  const id = randomUUID();
267
- const promise = new Promise((resolve2) => {
268
+ const promise = new Promise((resolve3) => {
268
269
  this.pending.set(id, {
269
270
  meta: { id, kind, prompt },
270
- resolve: resolve2
271
+ resolve: resolve3
271
272
  });
272
273
  });
273
274
  return { id, promise };
@@ -321,6 +322,8 @@ var SessionRuntime = class {
321
322
  config;
322
323
  model;
323
324
  autoApproveNormal;
325
+ /** 会话工作目录:绑定到启动会话的目录,所有文件类工具相对此解析 */
326
+ cwd;
324
327
  abortController = null;
325
328
  _stopAfterToolRound = false;
326
329
  _turnCount = 0;
@@ -335,6 +338,7 @@ var SessionRuntime = class {
335
338
  this.llm = opts.llm ?? createProvider(resolveActiveProfile(config2));
336
339
  this.model = resolveActiveProfile(config2).model;
337
340
  this.autoApproveNormal = opts.autoApproveNormal ?? false;
341
+ this.cwd = opts.cwd ?? process.cwd();
338
342
  if (opts.logFilePath) {
339
343
  this.logger = createLoggerAtPath(opts.logFilePath);
340
344
  } else if (config2.logDir) {
@@ -487,6 +491,10 @@ var SessionRuntime = class {
487
491
  * 再执行并将 stdout/stderr/exitCode 格式化为字符串返回。
488
492
  * 其他工具:直接执行,不需要审批流程。
489
493
  */
494
+ /** 把相对路径相对会话 cwd 解析为绝对路径;绝对路径与空值原样返回 */
495
+ resolveCwd(p) {
496
+ return p && !path.isAbsolute(p) ? path.resolve(this.cwd, p) : p;
497
+ }
490
498
  async executeToolCall(tc, signal) {
491
499
  const name = tc.name.toLowerCase().trim();
492
500
  const args = tc.arguments;
@@ -512,7 +520,7 @@ Proceed?`;
512
520
  }
513
521
  }
514
522
  if (signal.aborted) return SKIP_MESSAGE;
515
- const result = await executeBash(parsed.command);
523
+ const result = await executeBash(parsed.command, void 0, this.cwd);
516
524
  let output = "";
517
525
  if (result.stdout) output += result.stdout;
518
526
  if (result.stderr) output += result.stderr;
@@ -522,27 +530,27 @@ Proceed?`;
522
530
  }
523
531
  if (name === "read") {
524
532
  const parsed = JSON.parse(args);
525
- return await readFile(parsed);
533
+ return await readFile({ ...parsed, path: this.resolveCwd(parsed.path) });
526
534
  }
527
535
  if (name === "write") {
528
536
  const parsed = JSON.parse(args);
529
- return await writeFile(parsed);
537
+ return await writeFile({ ...parsed, path: this.resolveCwd(parsed.path) });
530
538
  }
531
539
  if (name === "edit") {
532
540
  const parsed = JSON.parse(args);
533
- return await editFile(parsed);
541
+ return await editFile({ ...parsed, path: this.resolveCwd(parsed.path) });
534
542
  }
535
543
  if (name === "glob") {
536
544
  const parsed = JSON.parse(args);
537
- return await globFiles(parsed);
545
+ return await globFiles({ ...parsed, cwd: parsed.cwd ?? this.cwd });
538
546
  }
539
547
  if (name === "grep") {
540
548
  const parsed = JSON.parse(args);
541
- return await grepFiles(parsed);
549
+ return await grepFiles({ ...parsed, cwd: parsed.cwd ?? this.cwd });
542
550
  }
543
551
  if (name === "apply_patch") {
544
552
  const parsed = JSON.parse(args);
545
- return await applyPatch(parsed);
553
+ return await applyPatch({ ...parsed, cwd: parsed.cwd ?? this.cwd });
546
554
  }
547
555
  if (name === "todo") {
548
556
  const parsed = JSON.parse(args);
@@ -802,15 +810,15 @@ if (rawArgs[0] === "web") {
802
810
  webAutoApprove = true;
803
811
  }
804
812
  }
805
- const { buildServer, generateAccessToken } = await import("./web-6WYKHML6.js");
813
+ const { buildServer, generateAccessToken } = await import("./web-24EDYYNA.js");
806
814
  const token = finalConfig.webToken ?? generateAccessToken();
807
815
  const manager = new SessionManager(finalConfig);
808
816
  const __webDirname = dirname(fileURLToPath(import.meta.url));
809
817
  const webRegistry = new SkillRegistry();
810
818
  for (const dir of [
811
- resolve(__webDirname, "../skills"),
812
- resolve(process.env.HOME ?? "~", ".ecode/skills"),
813
- resolve(process.cwd(), ".ecode/skills")
819
+ resolve2(__webDirname, "../skills"),
820
+ resolve2(process.env.HOME ?? "~", ".ecode/skills"),
821
+ resolve2(process.cwd(), ".ecode/skills")
814
822
  ]) {
815
823
  const skills = await loadSkillsFromDir(dir);
816
824
  for (const skill of skills) webRegistry.register(skill);
@@ -870,9 +878,9 @@ Press Ctrl+C to stop.
870
878
  }
871
879
  }
872
880
  const __dirname = dirname(fileURLToPath(import.meta.url));
873
- const builtinSkillsDir = resolve(__dirname, "../skills");
874
- const userSkillsDir = resolve(process.env.HOME ?? "~", ".ecode/skills");
875
- const projectSkillsDir = resolve(process.cwd(), ".ecode/skills");
881
+ const builtinSkillsDir = resolve2(__dirname, "../skills");
882
+ const userSkillsDir = resolve2(process.env.HOME ?? "~", ".ecode/skills");
883
+ const projectSkillsDir = resolve2(process.cwd(), ".ecode/skills");
876
884
  const registry = new SkillRegistry();
877
885
  for (const dir of [builtinSkillsDir, userSkillsDir, projectSkillsDir]) {
878
886
  const skills = await loadSkillsFromDir(dir);
@@ -899,7 +907,7 @@ Node.js 16/18 \u8BF7\u4F7F\u7528 --web \u6216 --pipe \u6A21\u5F0F\u3002
899
907
  );
900
908
  process.exit(1);
901
909
  }
902
- const { App, React, render, createStdinFilter } = await import("./ui-445CQEQR.js");
910
+ const { App, React, render, createStdinFilter } = await import("./ui-GQ6DSF7S.js");
903
911
  const stdinFilter = process.stdin.isTTY ? createStdinFilter(process.stdin) : process.stdin;
904
912
  render(
905
913
  React.createElement(App, { config: finalConfig, version: VERSION, autoMode, registry, trustedSkillDirs, initialMessages, stdinFilter }),
@@ -25,7 +25,7 @@ import {
25
25
  todo,
26
26
  webFetch,
27
27
  writeFile
28
- } from "./chunk-ZLF4HLQ7.js";
28
+ } from "./chunk-WHVNMO5M.js";
29
29
  import {
30
30
  handleSkillInput,
31
31
  loadJobs,
@@ -663,9 +663,10 @@ var Input = forwardRef(function Input2({ isActive, onSubmit, onChange, placehold
663
663
  return;
664
664
  }
665
665
  if (input.length > 0) {
666
- const newValue = v.slice(0, pos) + input + v.slice(pos);
666
+ const text = input.replace(/\r\n?/g, "\n");
667
+ const newValue = v.slice(0, pos) + text + v.slice(pos);
667
668
  setValueSync(newValue);
668
- setCursorPosSync(pos + input.length);
669
+ setCursorPosSync(pos + text.length);
669
670
  (_h = onChangeRef.current) == null ? void 0 : _h.call(onChangeRef, newValue);
670
671
  }
671
672
  },
@@ -1777,7 +1777,7 @@ async function chatRoutes(app, opts) {
1777
1777
  const logFilePath = join2(opts.config.logDir, session.logFile);
1778
1778
  const initialMessages = loadMessagesFromJsonl(logFilePath);
1779
1779
  try {
1780
- await manager.createSession({ sessionId: id, initialMessages, logFilePath });
1780
+ await manager.createSession({ sessionId: id, initialMessages, logFilePath, cwd: session.cwd });
1781
1781
  return reply.send({ success: true, resumed: true });
1782
1782
  } catch (err) {
1783
1783
  const msg = err instanceof Error ? err.message : String(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhongqian97-code/ecode",
3
- "version": "0.5.65",
3
+ "version": "0.5.67",
4
4
  "description": "A minimal Claude Code clone with REPL interface and bash tool calling",
5
5
  "type": "module",
6
6
  "author": "zhongqian97-code",