gitee-ai-employee 1.2.5 → 1.2.7

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.
package/dsh/client.js CHANGED
@@ -359,16 +359,12 @@ window.__ModuleLoader__.load({
359
359
  var accepted = 0
360
360
  var skipped = 0
361
361
  var tasks = repos.map(function (spec) {
362
- var platform = /^github:/i.test(spec) ? 'github' : /^gitee:/i.test(spec) ? 'gitee' : 'gitee'
363
- var rest = spec.replace(/^(github|gitee):/i, '')
364
- var idx = rest.indexOf('/')
365
- var owner = rest.slice(0, idx)
366
- var repo = rest.slice(idx + 1)
367
- if (!owner || !repo) return Promise.resolve({ accepted: false })
362
+ // 原始仓库行交给服务端统一解析(owner/repo、gitee:owner/repo、完整克隆地址均可)。
363
+ // 客户端不再自己 indexOf 切分——全路径 URL 会被切成 owner='https:' 导致克隆失败。
368
364
  return fetch('/gitee-ai/scan', {
369
365
  method: 'POST',
370
366
  headers: { 'Content-Type': 'application/json' },
371
- body: JSON.stringify({ platform: platform, owner: owner, repo: repo, dryRun: false }),
367
+ body: JSON.stringify({ spec: spec, dryRun: false }),
372
368
  }).then(function (r) { return r.json().catch(function () { return { accepted: false } }) })
373
369
  .then(function (b) {
374
370
  if (b && b.accepted) accepted++
package/dsh/index.js CHANGED
@@ -22,6 +22,15 @@ import { fileURLToPath } from "node:url";
22
22
  import { tmpdir, homedir } from "node:os";
23
23
  import { join } from "node:path";
24
24
 
25
+ // 路径分隔符:Windows 用反斜杠,mac / linux 用正斜杠(保证跨平台路径正确)。
26
+ const PATH_SEP = (typeof process !== "undefined" && process.platform === "win32") ? "\\" : "/";
27
+
28
+ // 插件自身版本(读包内 package.json),用于启动日志 / 状态接口自报,
29
+ // 便于在运行日志里一眼确认当前加载的到底是不是最新版。
30
+ const PLUGIN_VERSION = (() => {
31
+ try { return JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8")).version || "?"; } catch (e) { return "?"; }
32
+ })();
33
+
25
34
  const DEFAULT_CONFIG = {
26
35
  giteeToken: "",
27
36
  githubToken: "",
@@ -168,7 +177,7 @@ export default {
168
177
  let webServer = ctx.get("webServer");
169
178
  const shell = ctx.shell;
170
179
  const timer = ctx.timer;
171
- console.log("[gitee-ai] apply(composition) services ok: agents/shell/timer available; webServer=" + (webServer ? "yes" : "no") + " agentDefaultModel=" + (agentDefaultModel ? "yes" : "no"));
180
+ console.log("[gitee-ai] plugin v" + PLUGIN_VERSION + " loaded | " + ((typeof process !== "undefined" && process.platform) || "?") + " | node " + ((typeof process !== "undefined" && process.version) || "?"));
172
181
  ensureWorkerPreset();
173
182
 
174
183
  // ── 提示词归一化:兼容 {id:{name,prompt}} 与 [{id,name,prompt}] 两种形态 ──
@@ -371,12 +380,12 @@ export default {
371
380
  }
372
381
  }
373
382
  const stamp = Date.now() + "-" + (++apiSeq);
374
- const outFile = config.tmpDir + "\\gitee-out-" + stamp + ".json";
375
- const codeFile = config.tmpDir + "\\gitee-code-" + stamp + ".txt";
383
+ const outFile = config.tmpDir + PATH_SEP + "gitee-out-" + stamp + ".json";
384
+ const codeFile = config.tmpDir + PATH_SEP + "gitee-code-" + stamp + ".txt";
376
385
  let cmd;
377
386
  if (body !== undefined && body !== null) {
378
387
  const b64 = Buffer.from(JSON.stringify(body), "utf8").toString("base64");
379
- const tmp = config.tmpDir + "\\gitee-body-" + stamp + ".json";
388
+ const tmp = config.tmpDir + PATH_SEP + "gitee-body-" + stamp + ".json";
380
389
  cmd = `[IO.File]::WriteAllText('${tmp}', [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${b64}')), (New-Object System.Text.UTF8Encoding($false))); & 'C:\\Windows\\System32\\curl.exe' -sS -o '${outFile}' -w '%{http_code}' -X ${method} '${url}' -H 'Content-Type: application/json' -H 'Authorization: token ${token}' -d '@${tmp}' | Set-Content -Encoding ASCII '${codeFile}'`;
381
390
  } else {
382
391
  cmd = `& 'C:\\Windows\\System32\\curl.exe' -sS -o '${outFile}' -w '%{http_code}' '${url}' -H 'Authorization: token ${token}' | Set-Content -Encoding ASCII '${codeFile}'`;
@@ -480,10 +489,10 @@ export default {
480
489
  } catch (e) {
481
490
  diag.ok = false;
482
491
  diag.error = String((e && e.message) || e);
483
- try { writeFileSync(config.tmpDir + "\\gitee-my-repos-" + p + "-last.json", JSON.stringify(diag, null, 2), "utf8"); } catch (e2) {}
492
+ try { writeFileSync(config.tmpDir + PATH_SEP + "gitee-my-repos-" + p + "-last.json", JSON.stringify(diag, null, 2), "utf8"); } catch (e2) {}
484
493
  return { ok: false, error: diag.error };
485
494
  }
486
- try { writeFileSync(config.tmpDir + "\\gitee-my-repos-" + p + "-last.json", JSON.stringify(diag, null, 2), "utf8"); } catch (e2) {}
495
+ try { writeFileSync(config.tmpDir + PATH_SEP + "gitee-my-repos-" + p + "-last.json", JSON.stringify(diag, null, 2), "utf8"); } catch (e2) {}
487
496
  return { ok: true, repos: out };
488
497
  }
489
498
 
@@ -513,19 +522,16 @@ export default {
513
522
  return config.gitUser;
514
523
  }
515
524
 
516
- function repoDir(owner, repo) { return config.workRoot + "\\" + owner + "\\" + repo; }
525
+ function repoDir(owner, repo) { return config.workRoot + PATH_SEP + owner + PATH_SEP + repo; }
517
526
  function shellQuote(v) { return `'${String(v).replace(/'/g, "''")}'`; }
518
527
  async function ensureRepo(platform, owner, repo) {
519
528
  const dir = repoDir(owner, repo);
520
- try {
521
- const probe = await sh(`if (Test-Path '${dir.replace(/'/g, "''")}\\.git') { 'yes' } else { 'no' }`, { timeoutMs: 15000 });
522
- if ((probe.stdout.text || "").trim() === "yes") {
523
- await sh(`git -C ${shellQuote(dir)} fetch origin --prune --tags`, { timeoutMs: 300000 });
524
- return dir;
525
- }
526
- } catch (e) { /* fallthrough */ }
527
- const parent = config.workRoot + "\\" + owner;
528
- await sh(`New-Item -ItemType Directory -Force -Path ${shellQuote(parent)} | Out-Null`, { timeoutMs: 15000 });
529
+ // 跨平台检查是否已克隆:直接走文件系统,不依赖 PowerShell / shell 语法(mac / linux 亦可)
530
+ if (existsSync(dir + PATH_SEP + ".git")) {
531
+ await sh(`git -C ${shellQuote(dir)} fetch origin --prune --tags`, { timeoutMs: 300000 });
532
+ return dir;
533
+ }
534
+ mkdirSync(config.workRoot + PATH_SEP + owner, { recursive: true });
529
535
  const url = await cloneUrlFor(platform, owner, repo);
530
536
  const r = await sh(`git clone ${shellQuote(url)} ${shellQuote(dir)}`, { timeoutMs: 600000 });
531
537
  if (r.exitCode !== 0) {
@@ -677,8 +683,7 @@ export default {
677
683
  }
678
684
  async function readScanResult(resultFile) {
679
685
  try {
680
- const r = await sh(`Get-Content -Raw -Path ${shellQuote(resultFile)} -ErrorAction SilentlyContinue`, { timeoutMs: 20000 });
681
- const text = (r.stdout.text || "").trim();
686
+ const text = readFileSync(resultFile, "utf8").trim();
682
687
  if (!text) return { findings: [], note: "empty-result" };
683
688
  const parsed = JSON.parse(text);
684
689
  const arr = Array.isArray(parsed) ? parsed : (Array.isArray(parsed.findings) ? parsed.findings : []);
@@ -760,7 +765,6 @@ export default {
760
765
  const scanDir = join(dir, ".gitee-scan");
761
766
  const resultFile = join(scanDir, "result.json");
762
767
  try { mkdirSync(scanDir, { recursive: true }); } catch (e) {}
763
- void sh(`New-Item -ItemType Directory -Force -Path ${shellQuote(scanDir)} | Out-Null`, { timeoutMs: 15000 }).catch(() => {});
764
768
  const taskText = buildScanTask({ p, owner, repo, dir, commit, prompts, resultFile });
765
769
  let summary;
766
770
  try {
@@ -1664,7 +1668,7 @@ ${["critical", "high", "medium", "low", "none"].map((s) => `<option value="${s}"
1664
1668
  }
1665
1669
 
1666
1670
  // ── 扫描 API(固定路径,client 设置卡片调用)──
1667
- // POST /gitee-ai/scan {platform?,owner,repo,dryRun?,force?,prompts?,customPrompt?}
1671
+ // POST /gitee-ai/scan {spec}(原始仓库行,统一解析)或 {platform?,owner,repo,dryRun?,force?,prompts?,customPrompt?}
1668
1672
  // GET /gitee-ai/scan → 提示词清单 + 扫描任务 + 去重状态
1669
1673
  let scanApiDisposer = null;
1670
1674
  if (webServer) {
@@ -1682,9 +1686,22 @@ ${["critical", "high", "medium", "low", "none"].map((s) => `<option value="${s}"
1682
1686
  if (ct.includes("application/json")) {
1683
1687
  try { body = JSON.parse(raw || "{}"); } catch (e) { body = {}; }
1684
1688
  } else if (raw) body = parseForm(raw);
1685
- const platform = normPlatform(body.platform || config.defaultPlatform);
1686
- const owner = String(body.owner || "").trim();
1687
- const repo = String(body.repo || "").trim();
1689
+ let platform = normPlatform(body.platform || config.defaultPlatform);
1690
+ let owner = String(body.owner || "").trim();
1691
+ let repo = String(body.repo || "").trim();
1692
+ // 支持直接传原始仓库行(client「立即扫描全部仓库」就是传 spec 行):
1693
+ // 统一走 parseRepoSpec,兼容 owner/repo、gitee:/github: 前缀、完整克隆地址。
1694
+ // (不能在这里对 URL 用 indexOf('/') 切分——会把 https://… 切成 owner='https:')
1695
+ if (body.spec !== undefined && String(body.spec).trim()) {
1696
+ const parsed = parseRepoSpec(String(body.spec));
1697
+ if (!parsed) {
1698
+ send(res, 400, { ok: false, error: "无法解析仓库:" + String(body.spec) + "(支持 owner/repo、gitee:owner/repo、完整克隆地址)" });
1699
+ return;
1700
+ }
1701
+ platform = parsed.platform;
1702
+ owner = parsed.owner;
1703
+ repo = parsed.repo;
1704
+ }
1688
1705
  if (!owner || !repo) { send(res, 400, { ok: false, error: "owner/repo required" }); return; }
1689
1706
  const opts = {
1690
1707
  dryRun: body.dryRun === true || body.dryRun === "true",
@@ -1858,6 +1875,7 @@ ${["critical", "high", "medium", "low", "none"].map((s) => `<option value="${s}"
1858
1875
  workRoot: config.workRoot, autoMerge: config.autoMerge,
1859
1876
  autoCloseIssue: !!config.autoCloseIssue, tokenConfigured: tokenOk(),
1860
1877
  githubTokenConfigured: tokenOkFor("github"),
1878
+ version: PLUGIN_VERSION,
1861
1879
  defaultPlatform: config.defaultPlatform || "gitee",
1862
1880
  gitUser: config.gitUser || "", pollEnabled: !!config.pollEnabled,
1863
1881
  pollIntervalMs: config.pollIntervalMs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitee-ai-employee",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "Gitee/GitHub AI 员工:issue 里 @ 机器人自动开发并提 PR;v1.2 新增代码安全扫描——配置仓库地址后按内置/自定义提示词扫描漏洞,去重后提交 issue。An issue-driven AI developer for DeepSeek Harness (Gitee & GitHub) with optional static security scanning (dedup + issue reporting).",
5
5
  "license": "MIT",
6
6
  "type": "module",