@zhongqian97-code/ecode 0.5.9 → 0.5.11

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 (2) hide show
  1. package/dist/index.js +93 -31
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,8 +3,8 @@ const _ew=process.emitWarning.bind(process);process.emitWarning=function(w,...a)
3
3
 
4
4
  // src/index.ts
5
5
  import { createRequire } from "module";
6
- import { resolve as resolve6, dirname as dirname8 } from "path";
7
- import { fileURLToPath } from "url";
6
+ import { resolve as resolve5, dirname as dirname9 } from "path";
7
+ import { fileURLToPath as fileURLToPath2 } from "url";
8
8
  import React4 from "react";
9
9
  import { render } from "ink";
10
10
  import { readFileSync as readFileSync5 } from "fs";
@@ -540,13 +540,13 @@ function classifyCommand(cmd, dangerPatterns, _depth = 0) {
540
540
  import { exec } from "child_process";
541
541
  var DEFAULT_TIMEOUT_MS = 3e4;
542
542
  function executeBash(cmd, timeoutMs = DEFAULT_TIMEOUT_MS) {
543
- return new Promise((resolve7) => {
543
+ return new Promise((resolve6) => {
544
544
  exec(cmd, { timeout: timeoutMs }, (err, stdout, stderr) => {
545
545
  if (err) {
546
546
  const exitCode = err.code ?? 1;
547
- resolve7({ stdout: stdout ?? "", stderr: stderr ?? "", exitCode });
547
+ resolve6({ stdout: stdout ?? "", stderr: stderr ?? "", exitCode });
548
548
  } else {
549
- resolve7({ stdout: stdout ?? "", stderr: stderr ?? "", exitCode: 0 });
549
+ resolve6({ stdout: stdout ?? "", stderr: stderr ?? "", exitCode: 0 });
550
550
  }
551
551
  });
552
552
  });
@@ -2170,7 +2170,7 @@ function parseMouseScroll(data) {
2170
2170
 
2171
2171
  // src/ui/App.tsx
2172
2172
  import { homedir as homedir3 } from "os";
2173
- import { join as join10 } from "path";
2173
+ import { join as join11 } from "path";
2174
2174
 
2175
2175
  // src/automation/store.ts
2176
2176
  import { readFile as readFile8, writeFile as writeFile5, mkdir as mkdir2 } from "fs/promises";
@@ -2268,11 +2268,17 @@ async function executeJob(job, config2) {
2268
2268
 
2269
2269
  // src/automation/goal/evaluator.ts
2270
2270
  function parseVerdict(response) {
2271
- const lower = response.toLowerCase();
2272
- if (lower.includes("not_done")) return "not_done";
2273
- if (lower.includes("blocked")) return "blocked";
2274
- if (lower.includes("done")) return "done";
2275
- return "not_done";
2271
+ const scan = (text) => {
2272
+ if (/\bnot_done\b/.test(text)) return "not_done";
2273
+ if (/\bblocked\b/.test(text) && !/\bnot\s+blocked\b/.test(text)) return "blocked";
2274
+ if (/\bdone\b/.test(text) && !/\bnot\s+done\b/.test(text)) return "done";
2275
+ return null;
2276
+ };
2277
+ const firstLine = (response.split("\n")[0] ?? "").trim().toLowerCase();
2278
+ const fromFirstLine = scan(firstLine);
2279
+ if (fromFirstLine !== null) return fromFirstLine;
2280
+ const fromFull = scan(response.toLowerCase());
2281
+ return fromFull ?? "not_done";
2276
2282
  }
2277
2283
  function buildPrompt(input) {
2278
2284
  return [
@@ -2487,12 +2493,38 @@ async function cmdLoop(args, deps) {
2487
2493
  const spaceIdx = trimmed.indexOf(" ");
2488
2494
  if (spaceIdx !== -1) {
2489
2495
  const firstToken = trimmed.slice(0, spaceIdx);
2490
- const parsed = parseInterval(firstToken);
2496
+ const rest = trimmed.slice(spaceIdx + 1);
2497
+ const parsed1 = parseInterval(firstToken);
2498
+ if (parsed1 !== null) {
2499
+ intervalMs = parsed1.intervalMs;
2500
+ prompt = rest.trim();
2501
+ } else {
2502
+ const secondSpaceIdx = rest.indexOf(" ");
2503
+ if (secondSpaceIdx !== -1) {
2504
+ const twoToken = `${firstToken} ${rest.slice(0, secondSpaceIdx)}`;
2505
+ const parsed2 = parseInterval(twoToken);
2506
+ if (parsed2 !== null) {
2507
+ intervalMs = parsed2.intervalMs;
2508
+ prompt = rest.slice(secondSpaceIdx + 1).trim();
2509
+ }
2510
+ } else {
2511
+ const parsed2 = parseInterval(`${firstToken} ${rest}`);
2512
+ if (parsed2 !== null) {
2513
+ intervalMs = parsed2.intervalMs;
2514
+ prompt = "";
2515
+ }
2516
+ }
2517
+ }
2518
+ } else {
2519
+ const parsed = parseInterval(trimmed);
2491
2520
  if (parsed !== null) {
2492
2521
  intervalMs = parsed.intervalMs;
2493
- prompt = trimmed.slice(spaceIdx + 1).trim();
2522
+ prompt = "";
2494
2523
  }
2495
2524
  }
2525
+ if (!prompt.trim()) {
2526
+ return "\u7528\u6CD5\uFF1A/loop [interval] <prompt>\uFF0C\u4F8B\u5982\uFF1A/loop 10m \u68C0\u67E5 deploy \u72B6\u6001";
2527
+ }
2496
2528
  const now = /* @__PURE__ */ new Date();
2497
2529
  const job = {
2498
2530
  id: randomUUID2(),
@@ -2542,6 +2574,9 @@ async function cmdUnloop(idOrPrefix, deps) {
2542
2574
  import { randomUUID as randomUUID3 } from "crypto";
2543
2575
  async function cmdGoal(args, deps) {
2544
2576
  const condition = args.trim();
2577
+ if (!condition) {
2578
+ return "\u7528\u6CD5\uFF1A/goal <\u76EE\u6807\u6761\u4EF6>\uFF0C\u4F8B\u5982\uFF1A/goal \u6240\u6709\u6D4B\u8BD5\u901A\u8FC7";
2579
+ }
2545
2580
  const now = /* @__PURE__ */ new Date();
2546
2581
  const job = {
2547
2582
  id: randomUUID3(),
@@ -2784,11 +2819,11 @@ var AutomationManager = class {
2784
2819
  job.id,
2785
2820
  `[goal ${job.id.slice(0, 8)}] \u7B2C ${job.activeTurnCount} \u8F6E\uFF1A\u5C1A\u672A\u5B8C\u6210\uFF0C\u7EE7\u7EED\u6267\u884C\u2026`
2786
2821
  );
2787
- await new Promise((resolve7) => {
2788
- const timer = setTimeout(resolve7, 5e3);
2822
+ await new Promise((resolve6) => {
2823
+ const timer = setTimeout(resolve6, 5e3);
2789
2824
  signal.addEventListener("abort", () => {
2790
2825
  clearTimeout(timer);
2791
- resolve7();
2826
+ resolve6();
2792
2827
  }, { once: true });
2793
2828
  });
2794
2829
  }
@@ -2877,6 +2912,7 @@ function generateTitle(firstUserMessage) {
2877
2912
  // src/meta_skill/index.ts
2878
2913
  import * as fs11 from "fs";
2879
2914
  import * as path9 from "path";
2915
+ import { fileURLToPath } from "url";
2880
2916
 
2881
2917
  // src/meta_skill/task-classifier.ts
2882
2918
  var RULES = {
@@ -3591,18 +3627,44 @@ import * as os from "os";
3591
3627
  var STORE_PATH = path8.resolve(os.homedir(), ".ecode", "learning-records.jsonl");
3592
3628
 
3593
3629
  // src/meta_skill/index.ts
3630
+ function resolveBuiltinSkillsDir() {
3631
+ try {
3632
+ let dir = path9.dirname(fileURLToPath(import.meta.url));
3633
+ for (let i = 0; i < 4; i++) {
3634
+ const candidate = path9.join(dir, "skills");
3635
+ if (fs11.existsSync(candidate) && fs11.statSync(candidate).isDirectory()) {
3636
+ const hasSkillContent = fs11.readdirSync(candidate).some(
3637
+ (entry) => fs11.existsSync(path9.join(candidate, entry, "SKILL.md"))
3638
+ );
3639
+ if (hasSkillContent) return candidate;
3640
+ }
3641
+ const parent = path9.dirname(dir);
3642
+ if (parent === dir) break;
3643
+ dir = parent;
3644
+ }
3645
+ } catch {
3646
+ }
3647
+ return null;
3648
+ }
3594
3649
  function runMetaAlign(input) {
3595
3650
  const taskType = input.task.type && isValidTaskType(input.task.type) ? input.task.type : classifyTask(input.task.goal);
3596
3651
  const inheritedSkills = getBaselineSkills(taskType);
3652
+ const builtinSkillsDir2 = resolveBuiltinSkillsDir();
3597
3653
  const allSteps = [];
3598
3654
  for (const skillName of inheritedSkills) {
3599
- const primaryPath = path9.resolve(process.cwd(), "skills", skillName, "SKILL.md");
3600
- const fallbackPath = path9.resolve(process.cwd(), "skills", skillName + ".md");
3655
+ const candidates = [];
3656
+ if (builtinSkillsDir2) {
3657
+ candidates.push(path9.join(builtinSkillsDir2, skillName, "SKILL.md"));
3658
+ candidates.push(path9.join(builtinSkillsDir2, skillName + ".md"));
3659
+ }
3660
+ candidates.push(path9.join(process.cwd(), "skills", skillName, "SKILL.md"));
3661
+ candidates.push(path9.join(process.cwd(), "skills", skillName + ".md"));
3601
3662
  let body = "";
3602
- if (fs11.existsSync(primaryPath)) {
3603
- body = fs11.readFileSync(primaryPath, { encoding: "utf-8" });
3604
- } else if (fs11.existsSync(fallbackPath)) {
3605
- body = fs11.readFileSync(fallbackPath, { encoding: "utf-8" });
3663
+ for (const p of candidates) {
3664
+ if (fs11.existsSync(p)) {
3665
+ body = fs11.readFileSync(p, { encoding: "utf-8" });
3666
+ break;
3667
+ }
3606
3668
  }
3607
3669
  const steps = extractWorkflowSteps(body);
3608
3670
  allSteps.push(...steps);
@@ -3790,7 +3852,7 @@ function App({ config: config2, version: version2, autoMode: autoMode2 = false,
3790
3852
  const pendingConfirmRef = useRef2(null);
3791
3853
  const abortControllerRef = useRef2(null);
3792
3854
  const llmRef = useRef2(llmClient ?? createProvider(resolveActiveProfile(config2)));
3793
- const automationDataDir = config2.logDir ? join10(config2.logDir, "automation") : join10(homedir3(), ".config", "ecode", "automation");
3855
+ const automationDataDir = config2.logDir ? join11(config2.logDir, "automation") : join11(homedir3(), ".config", "ecode", "automation");
3794
3856
  const automationManagerRef = useRef2(
3795
3857
  new AutomationManager({
3796
3858
  dataDir: automationDataDir,
@@ -3996,10 +4058,10 @@ function App({ config: config2, version: version2, autoMode: autoMode2 = false,
3996
4058
  }
3997
4059
  });
3998
4060
  const confirm = useCallback((prompt) => {
3999
- return new Promise((resolve7) => {
4061
+ return new Promise((resolve6) => {
4000
4062
  setStatus("awaiting_confirm");
4001
4063
  setConfirmPrompt(prompt);
4002
- pendingConfirmRef.current = { resolve: resolve7 };
4064
+ pendingConfirmRef.current = { resolve: resolve6 };
4003
4065
  });
4004
4066
  }, []);
4005
4067
  const runLlmLoop = useCallback(
@@ -4522,13 +4584,13 @@ async function runPipe(prompt, llm, out = process.stdout, systemPrompt) {
4522
4584
  }
4523
4585
  }
4524
4586
  function readStdin() {
4525
- return new Promise((resolve7, reject) => {
4587
+ return new Promise((resolve6, reject) => {
4526
4588
  let data = "";
4527
4589
  process.stdin.setEncoding("utf-8");
4528
4590
  process.stdin.on("data", (chunk) => {
4529
4591
  data += chunk;
4530
4592
  });
4531
- process.stdin.on("end", () => resolve7(data.trim()));
4593
+ process.stdin.on("end", () => resolve6(data.trim()));
4532
4594
  process.stdin.on("error", reject);
4533
4595
  });
4534
4596
  }
@@ -4697,10 +4759,10 @@ if (replayFile) {
4697
4759
  process.exit(1);
4698
4760
  }
4699
4761
  }
4700
- var __dirname = dirname8(fileURLToPath(import.meta.url));
4701
- var builtinSkillsDir = resolve6(__dirname, "../skills");
4702
- var userSkillsDir = resolve6(process.env.HOME ?? "~", ".ecode/skills");
4703
- var projectSkillsDir = resolve6(process.cwd(), ".ecode/skills");
4762
+ var __dirname = dirname9(fileURLToPath2(import.meta.url));
4763
+ var builtinSkillsDir = resolve5(__dirname, "../skills");
4764
+ var userSkillsDir = resolve5(process.env.HOME ?? "~", ".ecode/skills");
4765
+ var projectSkillsDir = resolve5(process.cwd(), ".ecode/skills");
4704
4766
  var registry = new SkillRegistry();
4705
4767
  for (const dir of [builtinSkillsDir, userSkillsDir, projectSkillsDir]) {
4706
4768
  const skills = await loadSkillsFromDir(dir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhongqian97-code/ecode",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "description": "A minimal Claude Code clone with REPL interface and bash tool calling",
5
5
  "type": "module",
6
6
  "author": "zhongqian97-code",