@ai-setting/roy-agent-cli 1.6.6 → 1.6.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.
@@ -7426,7 +7426,7 @@ var require_dist = __commonJS((exports) => {
7426
7426
  var require_package = __commonJS((exports, module) => {
7427
7427
  module.exports = {
7428
7428
  name: "@ai-setting/roy-agent-cli",
7429
- version: "1.6.6",
7429
+ version: "1.6.7",
7430
7430
  type: "module",
7431
7431
  description: "CLI for roy-agent - Non-interactive command execution",
7432
7432
  main: "./dist/index.js",
@@ -9281,9 +9281,8 @@ bgprocess: ${bgProcessId}`;
9281
9281
  Task #${taskId}`;
9282
9282
  }
9283
9283
  if (result) {
9284
- const truncatedResult = result.length > 1e4 ? result.substring(0, 100) + "...[TRUNCATED]" : result;
9285
9284
  message += `
9286
- 结果: ${truncatedResult}`;
9285
+ 结果: ${result}`;
9287
9286
  }
9288
9287
  message += this.appendSubSessionId(payload);
9289
9288
  return message;
@@ -17476,6 +17475,47 @@ function resolveServerUrl(serverUrl, fallback) {
17476
17475
  return trimmed;
17477
17476
  }
17478
17477
 
17478
+ // src/lib/bounty-profile-reader.ts
17479
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
17480
+ import { homedir } from "node:os";
17481
+ import { join } from "node:path";
17482
+ function readBountyProfile(name, profilesDir) {
17483
+ if (!name)
17484
+ return null;
17485
+ const dir = profilesDir ?? join(homedir(), ".config", "bounty", "profiles");
17486
+ const profilePath = join(dir, `${name}.json`);
17487
+ if (!existsSync2(profilePath))
17488
+ return null;
17489
+ try {
17490
+ const raw = readFileSync(profilePath, "utf-8");
17491
+ const data = JSON.parse(raw);
17492
+ return {
17493
+ email: typeof data.email === "string" ? data.email : undefined,
17494
+ agent_id: typeof data.agent_id === "string" ? data.agent_id : undefined,
17495
+ api_base: typeof data.api_base === "string" ? data.api_base : undefined
17496
+ };
17497
+ } catch {
17498
+ return null;
17499
+ }
17500
+ }
17501
+ function profileToWsUrl(apiBase) {
17502
+ let url = apiBase.replace(/\/+$/, "");
17503
+ if (url.startsWith("ws://") || url.startsWith("wss://")) {
17504
+ if (url.endsWith("/ws"))
17505
+ return url;
17506
+ return `${url}/ws`;
17507
+ }
17508
+ if (url.startsWith("https://")) {
17509
+ url = "wss://" + url.slice("https://".length);
17510
+ } else if (url.startsWith("http://")) {
17511
+ url = "ws://" + url.slice("http://".length);
17512
+ }
17513
+ if (!url.endsWith("/ws")) {
17514
+ url = `${url}/ws`;
17515
+ }
17516
+ return url;
17517
+ }
17518
+
17479
17519
  // src/commands/eventsource/add.ts
17480
17520
  function uuid() {
17481
17521
  return generateId();
@@ -17511,10 +17551,13 @@ var EventSourceAddCommand = {
17511
17551
  describe: "Cron 表达式",
17512
17552
  type: "string"
17513
17553
  }).option("profile", {
17514
- describe: "lark-cli profile(lark-cli 类型用,多 appId 场景必要,参考 #1637)",
17554
+ describe: "Profile 名称(lark-cli / bounty-im 类型用,从 ~/.config/bounty/profiles/<name>.json 读取配置;多 appId / 多账户场景必要,参考 #1637)",
17515
17555
  type: "string"
17516
17556
  }).option("address", {
17517
- describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host)",
17557
+ describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host,v0.12 向后兼容)",
17558
+ type: "string"
17559
+ }).option("email", {
17560
+ describe: "Agent IM 注册邮箱(bounty-im 类型用,v0.13 server 协议;与 --profile 互斥)",
17518
17561
  type: "string"
17519
17562
  }).option("tls-skip-verify", {
17520
17563
  describe: "跳过 TLS 证书校验(bounty-im 类型用,wss:// 自签名场景,生产环境不推荐)",
@@ -17541,9 +17584,38 @@ var EventSourceAddCommand = {
17541
17584
  process.exit(1);
17542
17585
  }
17543
17586
  const eventTypes = a.eventTypes?.split(",").map((s) => s.trim());
17587
+ let resolvedEmail = a.email;
17588
+ let resolvedProfileName = a.profile;
17589
+ let profileApiBase;
17590
+ if (a.type === "bounty-im") {
17591
+ if (a.email && a.profile) {
17592
+ output.error(chalk59.red(`
17593
+ ✗ --email 和 --profile 互斥(profile 文件已包含 email)。请选择其一。
17594
+ `));
17595
+ process.exit(1);
17596
+ }
17597
+ if (a.profile) {
17598
+ const profile = readBountyProfile(a.profile);
17599
+ if (!profile) {
17600
+ output.error(chalk59.red(`
17601
+ ✗ Profile '${a.profile}' 不存在或格式错误。期望路径:~/.config/bounty/profiles/${a.profile}.json
17602
+ `));
17603
+ process.exit(1);
17604
+ }
17605
+ resolvedEmail = profile.email;
17606
+ profileApiBase = profile.api_base;
17607
+ }
17608
+ }
17544
17609
  const envUrl = process.env.BOUNTY_SERVER_URL;
17545
17610
  const fallback = envUrl || "http://localhost:8787";
17546
- const resolvedServerUrl = resolveServerUrl(a.serverUrl || a.imServerUrl, fallback);
17611
+ let resolvedServerUrl;
17612
+ if (a.serverUrl || a.imServerUrl) {
17613
+ resolvedServerUrl = resolveServerUrl(a.serverUrl || a.imServerUrl, fallback);
17614
+ } else if (a.type === "bounty-im" && profileApiBase) {
17615
+ resolvedServerUrl = profileToWsUrl(profileApiBase);
17616
+ } else {
17617
+ resolvedServerUrl = resolveServerUrl(undefined, fallback);
17618
+ }
17547
17619
  const config = {
17548
17620
  id: uuid(),
17549
17621
  name: a.name,
@@ -17555,6 +17627,7 @@ var EventSourceAddCommand = {
17555
17627
  interval: a.interval,
17556
17628
  cron: a.cron,
17557
17629
  profile: a.profile,
17630
+ email: resolvedEmail,
17558
17631
  address: a.address,
17559
17632
  imServerUrl: resolvedServerUrl,
17560
17633
  tlsSkipVerify: a.tlsSkipVerify === true,
@@ -17574,8 +17647,11 @@ var EventSourceAddCommand = {
17574
17647
  if (a.interval) {
17575
17648
  output.log(` Interval: ${chalk59.gray(`${a.interval}ms`)}`);
17576
17649
  }
17577
- if (a.profile) {
17578
- output.log(` Profile: ${chalk59.gray(a.profile)}`);
17650
+ if (resolvedProfileName) {
17651
+ output.log(` Profile: ${chalk59.gray(resolvedProfileName)}`);
17652
+ }
17653
+ if (resolvedEmail) {
17654
+ output.log(` Email: ${chalk59.gray(resolvedEmail)}`);
17579
17655
  }
17580
17656
  if (a.address) {
17581
17657
  output.log(` Address: ${chalk59.gray(a.address)}`);
@@ -17645,7 +17721,13 @@ var EventSourceUpdateCommand = {
17645
17721
  describe: "是否启用",
17646
17722
  type: "boolean"
17647
17723
  }).option("address", {
17648
- describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host)",
17724
+ describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host,v0.12 向后兼容)",
17725
+ type: "string"
17726
+ }).option("email", {
17727
+ describe: "Agent IM 注册邮箱(bounty-im 类型用,v0.13;与 --profile 互斥)",
17728
+ type: "string"
17729
+ }).option("profile", {
17730
+ describe: "Profile 名称(bounty-im 类型用,从 ~/.config/bounty/profiles/<name>.json 读取并自动更新 email + imServerUrl)",
17649
17731
  type: "string"
17650
17732
  }).option("tls-skip-verify", {
17651
17733
  describe: "跳过 TLS 证书校验(bounty-im 类型用,wss:// 自签名场景,生产环境不推荐)",
@@ -17680,6 +17762,25 @@ var EventSourceUpdateCommand = {
17680
17762
  }
17681
17763
  process.exit(1);
17682
17764
  }
17765
+ if (match.source.type === "bounty-im" && a.email && a.profile) {
17766
+ output.error(chalk60.red(`
17767
+ ✗ --email 和 --profile 互斥(profile 文件已包含 email)。请选择其一。
17768
+ `));
17769
+ process.exit(1);
17770
+ }
17771
+ let profileEmail;
17772
+ let profileApiBase;
17773
+ if (a.profile && match.source.type === "bounty-im") {
17774
+ const profile = readBountyProfile(a.profile);
17775
+ if (!profile) {
17776
+ output.error(chalk60.red(`
17777
+ ✗ Profile '${a.profile}' 不存在或格式错误。期望路径:~/.config/bounty/profiles/${a.profile}.json
17778
+ `));
17779
+ process.exit(1);
17780
+ }
17781
+ profileEmail = profile.email;
17782
+ profileApiBase = profile.api_base;
17783
+ }
17683
17784
  const partial = {};
17684
17785
  if (a.name !== undefined)
17685
17786
  partial.name = a.name;
@@ -17698,10 +17799,18 @@ var EventSourceUpdateCommand = {
17698
17799
  partial.enabled = a.enabled;
17699
17800
  if (a.address !== undefined)
17700
17801
  partial.address = a.address;
17701
- if (a.serverUrl !== undefined || a.imServerUrl !== undefined) {
17802
+ if (a.email !== undefined)
17803
+ partial.email = a.email;
17804
+ if (profileEmail !== undefined)
17805
+ partial.email = profileEmail;
17806
+ if (a.serverUrl !== undefined || a.imServerUrl !== undefined || profileApiBase !== undefined) {
17702
17807
  const envUrl = process.env.BOUNTY_SERVER_URL;
17703
17808
  const fallback = envUrl || "http://localhost:8787";
17704
- partial.imServerUrl = resolveServerUrl(a.serverUrl ?? a.imServerUrl, fallback);
17809
+ if (a.serverUrl !== undefined || a.imServerUrl !== undefined) {
17810
+ partial.imServerUrl = resolveServerUrl(a.serverUrl ?? a.imServerUrl, fallback);
17811
+ } else if (profileApiBase !== undefined) {
17812
+ partial.imServerUrl = profileToWsUrl(profileApiBase);
17813
+ }
17705
17814
  }
17706
17815
  if (a.tlsSkipVerify !== undefined)
17707
17816
  partial.tlsSkipVerify = a.tlsSkipVerify === true;
@@ -19147,6 +19256,121 @@ class DecoratorNodeValidator extends BaseNodeValidator {
19147
19256
  }
19148
19257
  }
19149
19258
 
19259
+ // src/commands/workflow/validators/nodes/python-call-node-validator.ts
19260
+ class PythonCallNodeValidator extends BaseNodeValidator {
19261
+ nodeType = "python_call";
19262
+ getRequiredFields() {
19263
+ return ["module", "function"];
19264
+ }
19265
+ validateTypeSpecific(node) {
19266
+ const errors = [];
19267
+ const config = node.config ?? {};
19268
+ const moduleVal = config.module;
19269
+ if (moduleVal === undefined || moduleVal === null) {
19270
+ errors.push({
19271
+ type: "MISSING_REQUIRED_FIELD" /* MISSING_REQUIRED_FIELD */,
19272
+ description: 'Field "module" is required for python_call node',
19273
+ expected: 'module: "<python.module.path>"',
19274
+ actual: "undefined",
19275
+ fix: 'Add `module: "<python.module.path>"` to the node config',
19276
+ nodeId: node.id
19277
+ });
19278
+ } else if (typeof moduleVal !== "string") {
19279
+ errors.push({
19280
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19281
+ description: 'Field "module" has invalid type',
19282
+ expected: 'string (Python module path, e.g. "investment_strategy.scripts.market_timing")',
19283
+ actual: typeof moduleVal,
19284
+ fix: "Change `module` to a string",
19285
+ nodeId: node.id
19286
+ });
19287
+ } else if (!/^[A-Za-z_]\w*(\.[A-Za-z_]\w*)*$/.test(moduleVal)) {
19288
+ errors.push({
19289
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19290
+ description: `Field "module" is not a valid Python module path: "${moduleVal}"`,
19291
+ expected: 'dotted identifier like "pkg.sub.mod"',
19292
+ actual: moduleVal,
19293
+ fix: "Use only letters, digits, underscores, and dots",
19294
+ nodeId: node.id
19295
+ });
19296
+ }
19297
+ const fnVal = config.function;
19298
+ if (fnVal === undefined || fnVal === null) {
19299
+ errors.push({
19300
+ type: "MISSING_REQUIRED_FIELD" /* MISSING_REQUIRED_FIELD */,
19301
+ description: 'Field "function" is required for python_call node',
19302
+ expected: 'function: "<python_function_name>"',
19303
+ actual: "undefined",
19304
+ fix: 'Add `function: "<name>"` to the node config',
19305
+ nodeId: node.id
19306
+ });
19307
+ } else if (typeof fnVal !== "string") {
19308
+ errors.push({
19309
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19310
+ description: 'Field "function" has invalid type',
19311
+ expected: 'string (Python function name, e.g. "run")',
19312
+ actual: typeof fnVal,
19313
+ fix: "Change `function` to a string",
19314
+ nodeId: node.id
19315
+ });
19316
+ } else if (!/^[A-Za-z_]\w*$/.test(fnVal)) {
19317
+ errors.push({
19318
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19319
+ description: `Field "function" is not a valid Python identifier: "${fnVal}"`,
19320
+ expected: "Python identifier: starts with letter/underscore, contains only [A-Za-z0-9_]",
19321
+ actual: fnVal,
19322
+ fix: "Use a plain Python function name (no dots, no operators)",
19323
+ nodeId: node.id
19324
+ });
19325
+ }
19326
+ const argsVal = config.args;
19327
+ if (argsVal !== undefined && (typeof argsVal !== "object" || argsVal === null || Array.isArray(argsVal))) {
19328
+ errors.push({
19329
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19330
+ description: 'Field "args" has invalid type',
19331
+ expected: "object (kwargs to pass to the function)",
19332
+ actual: Array.isArray(argsVal) ? "array" : typeof argsVal,
19333
+ fix: "Change `args` to an object: args: { key: value }",
19334
+ nodeId: node.id
19335
+ });
19336
+ }
19337
+ if (config.cwd !== undefined && typeof config.cwd !== "string") {
19338
+ errors.push({
19339
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19340
+ description: 'Field "cwd" has invalid type',
19341
+ expected: "string (filesystem path)",
19342
+ actual: typeof config.cwd,
19343
+ fix: "Change `cwd` to a string",
19344
+ nodeId: node.id
19345
+ });
19346
+ }
19347
+ if (config.python !== undefined && typeof config.python !== "string") {
19348
+ errors.push({
19349
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19350
+ description: 'Field "python" has invalid type',
19351
+ expected: "string (path to python interpreter)",
19352
+ actual: typeof config.python,
19353
+ fix: "Change `python` to a string",
19354
+ nodeId: node.id
19355
+ });
19356
+ }
19357
+ if (config.timeout !== undefined) {
19358
+ const t = config.timeout;
19359
+ if (typeof t !== "number" || !Number.isFinite(t) || t <= 0) {
19360
+ errors.push({
19361
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19362
+ description: 'Field "timeout" has invalid type',
19363
+ expected: "positive number (milliseconds)",
19364
+ actual: typeof t === "number" ? `${t}` : typeof t,
19365
+ fix: "Change `timeout` to a positive number, e.g. timeout: 60000",
19366
+ nodeId: node.id
19367
+ });
19368
+ }
19369
+ }
19370
+ return errors;
19371
+ }
19372
+ }
19373
+
19150
19374
  // src/commands/workflow/validators/node-validator-factory.ts
19151
19375
  var validators = new Map;
19152
19376
  validators.set("tool", new ToolNodeValidator);
@@ -19156,6 +19380,7 @@ validators.set("workflow", new WorkflowNodeValidator);
19156
19380
  validators.set("condition", new ConditionNodeValidator);
19157
19381
  validators.set("merge", new MergeNodeValidator);
19158
19382
  validators.set("decorator", new DecoratorNodeValidator);
19383
+ validators.set("python_call", new PythonCallNodeValidator);
19159
19384
  function getNodeValidator(type) {
19160
19385
  return validators.get(type) || null;
19161
19386
  }
@@ -20880,7 +21105,7 @@ Use `) + chalk74.cyan("roy-agent workflow nodes <type>") + chalk74.gray(" for de
20880
21105
 
20881
21106
  // src/commands/workflow/commands/validate.ts
20882
21107
  import chalk75 from "chalk";
20883
- import { readFileSync } from "fs";
21108
+ import { readFileSync as readFileSync2 } from "fs";
20884
21109
  async function parseWorkflowInput(input, yamlStr) {
20885
21110
  const parseYaml = async (content) => {
20886
21111
  const YAML2 = await Promise.resolve().then(() => __toESM(require_dist(), 1));
@@ -20888,7 +21113,7 @@ async function parseWorkflowInput(input, yamlStr) {
20888
21113
  };
20889
21114
  if (input && !yamlStr) {
20890
21115
  try {
20891
- const content = readFileSync(input, "utf-8");
21116
+ const content = readFileSync2(input, "utf-8");
20892
21117
  return await parseYaml(content);
20893
21118
  } catch (error) {
20894
21119
  throw new Error(`Failed to read file "${input}": ${error.message}`);
@@ -21623,24 +21848,24 @@ var LspCommand = {
21623
21848
 
21624
21849
  // src/commands/install/index.ts
21625
21850
  import { spawnSync } from "node:child_process";
21626
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync, mkdirSync, cpSync } from "node:fs";
21627
- import { join as join4, resolve } from "node:path";
21628
- import { homedir as homedir3 } from "node:os";
21851
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync, mkdirSync, cpSync } from "node:fs";
21852
+ import { join as join5, resolve } from "node:path";
21853
+ import { homedir as homedir4 } from "node:os";
21629
21854
  function getConfigDir(scope) {
21630
- return scope === "global" ? join4(homedir3(), ".roy-agent") : join4(process.cwd(), ".roy");
21855
+ return scope === "global" ? join5(homedir4(), ".roy-agent") : join5(process.cwd(), ".roy");
21631
21856
  }
21632
21857
  function detectDefaultScope() {
21633
- const projectDir = join4(process.cwd(), ".roy");
21634
- return existsSync3(projectDir) ? "project" : "global";
21858
+ const projectDir = join5(process.cwd(), ".roy");
21859
+ return existsSync4(projectDir) ? "project" : "global";
21635
21860
  }
21636
21861
  function getConfigPath(scope) {
21637
- return join4(getConfigDir(scope), "plugins.json");
21862
+ return join5(getConfigDir(scope), "plugins.json");
21638
21863
  }
21639
21864
  function loadPlugins(scope) {
21640
21865
  const configPath = getConfigPath(scope);
21641
21866
  try {
21642
- if (existsSync3(configPath)) {
21643
- const raw = readFileSync2(configPath, "utf-8");
21867
+ if (existsSync4(configPath)) {
21868
+ const raw = readFileSync3(configPath, "utf-8");
21644
21869
  const config = JSON.parse(raw);
21645
21870
  return config.plugins ?? [];
21646
21871
  }
@@ -21650,7 +21875,7 @@ function loadPlugins(scope) {
21650
21875
  function savePlugins(plugins, scope) {
21651
21876
  const configDir = getConfigDir(scope);
21652
21877
  const configPath = getConfigPath(scope);
21653
- if (!existsSync3(configDir)) {
21878
+ if (!existsSync4(configDir)) {
21654
21879
  mkdirSync(configDir, { recursive: true });
21655
21880
  }
21656
21881
  const config = { plugins };
@@ -21666,10 +21891,10 @@ function stripVersionSpec(packageName) {
21666
21891
  function readPackageInfo(packageName) {
21667
21892
  const bareName = packageName.startsWith("/") || packageName.startsWith(".") ? packageName : stripVersionSpec(packageName);
21668
21893
  if (packageName.startsWith("/") || packageName.startsWith(".")) {
21669
- const localPkgPath = join4(packageName, "package.json");
21670
- if (existsSync3(localPkgPath)) {
21894
+ const localPkgPath = join5(packageName, "package.json");
21895
+ if (existsSync4(localPkgPath)) {
21671
21896
  try {
21672
- const pkg = JSON.parse(readFileSync2(localPkgPath, "utf-8"));
21897
+ const pkg = JSON.parse(readFileSync3(localPkgPath, "utf-8"));
21673
21898
  return {
21674
21899
  version: pkg.version ?? "0.0.0",
21675
21900
  name: pkg.name ?? packageName,
@@ -21681,19 +21906,19 @@ function readPackageInfo(packageName) {
21681
21906
  }
21682
21907
  }
21683
21908
  const searchPaths = [
21684
- join4(process.cwd(), "node_modules", bareName, "package.json"),
21909
+ join5(process.cwd(), "node_modules", bareName, "package.json"),
21685
21910
  resolve(process.cwd(), "..", "node_modules", bareName, "package.json"),
21686
- join4(process.cwd(), ".roy", "plugins", bareName, "package.json"),
21687
- join4(homedir3(), ".roy-agent", "node_modules", bareName, "package.json"),
21911
+ join5(process.cwd(), ".roy", "plugins", bareName, "package.json"),
21912
+ join5(homedir4(), ".roy-agent", "node_modules", bareName, "package.json"),
21688
21913
  ...(() => {
21689
21914
  const globalRoot = getNpmGlobalRoot();
21690
- return globalRoot ? [join4(globalRoot, bareName, "package.json")] : [];
21915
+ return globalRoot ? [join5(globalRoot, bareName, "package.json")] : [];
21691
21916
  })()
21692
21917
  ];
21693
21918
  for (const pkgPath of searchPaths) {
21694
21919
  try {
21695
- if (existsSync3(pkgPath)) {
21696
- const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
21920
+ if (existsSync4(pkgPath)) {
21921
+ const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
21697
21922
  return {
21698
21923
  version: pkg.version ?? "0.0.0",
21699
21924
  name: pkg.name ?? bareName,
@@ -21716,15 +21941,15 @@ function getNpmGlobalRoot() {
21716
21941
  return null;
21717
21942
  }
21718
21943
  function getPackageManagerCommand() {
21719
- if (existsSync3(join4(process.cwd(), "pnpm-lock.yaml"))) {
21720
- if (existsSync3(join4(process.cwd(), "pnpm-workspace.yaml"))) {
21944
+ if (existsSync4(join5(process.cwd(), "pnpm-lock.yaml"))) {
21945
+ if (existsSync4(join5(process.cwd(), "pnpm-workspace.yaml"))) {
21721
21946
  return "pnpm -w";
21722
21947
  }
21723
21948
  return "pnpm";
21724
21949
  }
21725
- if (existsSync3(join4(process.cwd(), "yarn.lock")))
21950
+ if (existsSync4(join5(process.cwd(), "yarn.lock")))
21726
21951
  return "yarn";
21727
- if (existsSync3(join4(process.cwd(), "bun.lock")) || existsSync3(join4(process.cwd(), "bun.lockb")))
21952
+ if (existsSync4(join5(process.cwd(), "bun.lock")) || existsSync4(join5(process.cwd(), "bun.lockb")))
21728
21953
  return "bun";
21729
21954
  return "npm";
21730
21955
  }
@@ -21763,14 +21988,14 @@ var InstallPackageCommand = {
21763
21988
  }
21764
21989
  resolvedName = info2.name;
21765
21990
  const srcDir = resolve(packageName);
21766
- if (!existsSync3(srcDir)) {
21991
+ if (!existsSync4(srcDir)) {
21767
21992
  console.error(`
21768
21993
  ❌ Local path '${srcDir}' does not exist.
21769
21994
  `);
21770
21995
  process.exit(1);
21771
21996
  }
21772
- const pluginDir = join4(process.cwd(), ".roy", "plugins", resolvedName);
21773
- if (!existsSync3(pluginDir)) {
21997
+ const pluginDir = join5(process.cwd(), ".roy", "plugins", resolvedName);
21998
+ if (!existsSync4(pluginDir)) {
21774
21999
  mkdirSync(pluginDir, { recursive: true });
21775
22000
  }
21776
22001
  const result = spawnSync("cp", ["-r", `${srcDir}/.`, pluginDir], {
@@ -21805,12 +22030,12 @@ var InstallPackageCommand = {
21805
22030
  process.exit(1);
21806
22031
  }
21807
22032
  resolvedName = info2.name;
21808
- const pluginDir = join4(process.cwd(), ".roy", "plugins", resolvedName);
21809
- if (!existsSync3(pluginDir)) {
22033
+ const pluginDir = join5(process.cwd(), ".roy", "plugins", resolvedName);
22034
+ if (!existsSync4(pluginDir)) {
21810
22035
  mkdirSync(pluginDir, { recursive: true });
21811
22036
  }
21812
- const nmPath = join4(process.cwd(), "node_modules", packageName);
21813
- if (existsSync3(nmPath)) {
22037
+ const nmPath = join5(process.cwd(), "node_modules", packageName);
22038
+ if (existsSync4(nmPath)) {
21814
22039
  spawnSync("cp", ["-r", `${nmPath}/.`, pluginDir], { stdio: "inherit", shell: false });
21815
22040
  }
21816
22041
  }
@@ -21841,14 +22066,14 @@ var InstallPackageCommand = {
21841
22066
  `);
21842
22067
  process.exit(1);
21843
22068
  }
21844
- const globalNm = join4(homedir3(), ".roy-agent", "node_modules", resolvedGlobalName);
21845
- if (!existsSync3(globalNm)) {
21846
- mkdirSync(join4(homedir3(), ".roy-agent", "node_modules"), { recursive: true });
22069
+ const globalNm = join5(homedir4(), ".roy-agent", "node_modules", resolvedGlobalName);
22070
+ if (!existsSync4(globalNm)) {
22071
+ mkdirSync(join5(homedir4(), ".roy-agent", "node_modules"), { recursive: true });
21847
22072
  const rootResult = spawnSync("npm", ["root", "-g"], { stdio: "pipe", shell: false });
21848
22073
  const globalRoot = rootResult.stdout?.toString().trim();
21849
22074
  if (globalRoot) {
21850
- const globalInstalled = join4(globalRoot, resolvedGlobalName);
21851
- if (existsSync3(globalInstalled)) {
22075
+ const globalInstalled = join5(globalRoot, resolvedGlobalName);
22076
+ if (existsSync4(globalInstalled)) {
21852
22077
  cpSync(globalInstalled, globalNm, { recursive: true });
21853
22078
  }
21854
22079
  }
@@ -21959,8 +22184,8 @@ var InstallRemoveCommand = {
21959
22184
  \uD83D\uDDD1️ Removing plugin: ${plugin.packageName}@${plugin.version} (${scope})
21960
22185
  `);
21961
22186
  if (scope === "project") {
21962
- const pluginDir = join4(process.cwd(), ".roy", "plugins", plugin.packageName);
21963
- if (existsSync3(pluginDir)) {
22187
+ const pluginDir = join5(process.cwd(), ".roy", "plugins", plugin.packageName);
22188
+ if (existsSync4(pluginDir)) {
21964
22189
  spawnSync("rm", ["-rf", pluginDir], { stdio: "inherit", shell: false });
21965
22190
  console.log(` Removed plugin directory: ${pluginDir}`);
21966
22191
  }
@@ -21975,8 +22200,8 @@ var InstallRemoveCommand = {
21975
22200
  `);
21976
22201
  process.exit(result.status ?? 1);
21977
22202
  }
21978
- const globalNm = join4(homedir3(), ".roy-agent", "node_modules", plugin.packageName);
21979
- if (existsSync3(globalNm)) {
22203
+ const globalNm = join5(homedir4(), ".roy-agent", "node_modules", plugin.packageName);
22204
+ if (existsSync4(globalNm)) {
21980
22205
  spawnSync("rm", ["-rf", globalNm], { stdio: "inherit", shell: false });
21981
22206
  }
21982
22207
  }
package/dist/index.js CHANGED
@@ -7425,7 +7425,7 @@ var require_dist = __commonJS((exports) => {
7425
7425
  var require_package = __commonJS((exports, module) => {
7426
7426
  module.exports = {
7427
7427
  name: "@ai-setting/roy-agent-cli",
7428
- version: "1.6.6",
7428
+ version: "1.6.7",
7429
7429
  type: "module",
7430
7430
  description: "CLI for roy-agent - Non-interactive command execution",
7431
7431
  main: "./dist/index.js",
@@ -9280,9 +9280,8 @@ bgprocess: ${bgProcessId}`;
9280
9280
  Task #${taskId}`;
9281
9281
  }
9282
9282
  if (result) {
9283
- const truncatedResult = result.length > 1e4 ? result.substring(0, 100) + "...[TRUNCATED]" : result;
9284
9283
  message += `
9285
- 结果: ${truncatedResult}`;
9284
+ 结果: ${result}`;
9286
9285
  }
9287
9286
  message += this.appendSubSessionId(payload);
9288
9287
  return message;
@@ -17475,6 +17474,47 @@ function resolveServerUrl(serverUrl, fallback) {
17475
17474
  return trimmed;
17476
17475
  }
17477
17476
 
17477
+ // src/lib/bounty-profile-reader.ts
17478
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
17479
+ import { homedir } from "node:os";
17480
+ import { join } from "node:path";
17481
+ function readBountyProfile(name, profilesDir) {
17482
+ if (!name)
17483
+ return null;
17484
+ const dir = profilesDir ?? join(homedir(), ".config", "bounty", "profiles");
17485
+ const profilePath = join(dir, `${name}.json`);
17486
+ if (!existsSync2(profilePath))
17487
+ return null;
17488
+ try {
17489
+ const raw = readFileSync(profilePath, "utf-8");
17490
+ const data = JSON.parse(raw);
17491
+ return {
17492
+ email: typeof data.email === "string" ? data.email : undefined,
17493
+ agent_id: typeof data.agent_id === "string" ? data.agent_id : undefined,
17494
+ api_base: typeof data.api_base === "string" ? data.api_base : undefined
17495
+ };
17496
+ } catch {
17497
+ return null;
17498
+ }
17499
+ }
17500
+ function profileToWsUrl(apiBase) {
17501
+ let url = apiBase.replace(/\/+$/, "");
17502
+ if (url.startsWith("ws://") || url.startsWith("wss://")) {
17503
+ if (url.endsWith("/ws"))
17504
+ return url;
17505
+ return `${url}/ws`;
17506
+ }
17507
+ if (url.startsWith("https://")) {
17508
+ url = "wss://" + url.slice("https://".length);
17509
+ } else if (url.startsWith("http://")) {
17510
+ url = "ws://" + url.slice("http://".length);
17511
+ }
17512
+ if (!url.endsWith("/ws")) {
17513
+ url = `${url}/ws`;
17514
+ }
17515
+ return url;
17516
+ }
17517
+
17478
17518
  // src/commands/eventsource/add.ts
17479
17519
  function uuid() {
17480
17520
  return generateId();
@@ -17510,10 +17550,13 @@ var EventSourceAddCommand = {
17510
17550
  describe: "Cron 表达式",
17511
17551
  type: "string"
17512
17552
  }).option("profile", {
17513
- describe: "lark-cli profile(lark-cli 类型用,多 appId 场景必要,参考 #1637)",
17553
+ describe: "Profile 名称(lark-cli / bounty-im 类型用,从 ~/.config/bounty/profiles/<name>.json 读取配置;多 appId / 多账户场景必要,参考 #1637)",
17514
17554
  type: "string"
17515
17555
  }).option("address", {
17516
- describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host)",
17556
+ describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host,v0.12 向后兼容)",
17557
+ type: "string"
17558
+ }).option("email", {
17559
+ describe: "Agent IM 注册邮箱(bounty-im 类型用,v0.13 server 协议;与 --profile 互斥)",
17517
17560
  type: "string"
17518
17561
  }).option("tls-skip-verify", {
17519
17562
  describe: "跳过 TLS 证书校验(bounty-im 类型用,wss:// 自签名场景,生产环境不推荐)",
@@ -17540,9 +17583,38 @@ var EventSourceAddCommand = {
17540
17583
  process.exit(1);
17541
17584
  }
17542
17585
  const eventTypes = a.eventTypes?.split(",").map((s) => s.trim());
17586
+ let resolvedEmail = a.email;
17587
+ let resolvedProfileName = a.profile;
17588
+ let profileApiBase;
17589
+ if (a.type === "bounty-im") {
17590
+ if (a.email && a.profile) {
17591
+ output.error(chalk59.red(`
17592
+ ✗ --email 和 --profile 互斥(profile 文件已包含 email)。请选择其一。
17593
+ `));
17594
+ process.exit(1);
17595
+ }
17596
+ if (a.profile) {
17597
+ const profile = readBountyProfile(a.profile);
17598
+ if (!profile) {
17599
+ output.error(chalk59.red(`
17600
+ ✗ Profile '${a.profile}' 不存在或格式错误。期望路径:~/.config/bounty/profiles/${a.profile}.json
17601
+ `));
17602
+ process.exit(1);
17603
+ }
17604
+ resolvedEmail = profile.email;
17605
+ profileApiBase = profile.api_base;
17606
+ }
17607
+ }
17543
17608
  const envUrl = process.env.BOUNTY_SERVER_URL;
17544
17609
  const fallback = envUrl || "http://localhost:8787";
17545
- const resolvedServerUrl = resolveServerUrl(a.serverUrl || a.imServerUrl, fallback);
17610
+ let resolvedServerUrl;
17611
+ if (a.serverUrl || a.imServerUrl) {
17612
+ resolvedServerUrl = resolveServerUrl(a.serverUrl || a.imServerUrl, fallback);
17613
+ } else if (a.type === "bounty-im" && profileApiBase) {
17614
+ resolvedServerUrl = profileToWsUrl(profileApiBase);
17615
+ } else {
17616
+ resolvedServerUrl = resolveServerUrl(undefined, fallback);
17617
+ }
17546
17618
  const config = {
17547
17619
  id: uuid(),
17548
17620
  name: a.name,
@@ -17554,6 +17626,7 @@ var EventSourceAddCommand = {
17554
17626
  interval: a.interval,
17555
17627
  cron: a.cron,
17556
17628
  profile: a.profile,
17629
+ email: resolvedEmail,
17557
17630
  address: a.address,
17558
17631
  imServerUrl: resolvedServerUrl,
17559
17632
  tlsSkipVerify: a.tlsSkipVerify === true,
@@ -17573,8 +17646,11 @@ var EventSourceAddCommand = {
17573
17646
  if (a.interval) {
17574
17647
  output.log(` Interval: ${chalk59.gray(`${a.interval}ms`)}`);
17575
17648
  }
17576
- if (a.profile) {
17577
- output.log(` Profile: ${chalk59.gray(a.profile)}`);
17649
+ if (resolvedProfileName) {
17650
+ output.log(` Profile: ${chalk59.gray(resolvedProfileName)}`);
17651
+ }
17652
+ if (resolvedEmail) {
17653
+ output.log(` Email: ${chalk59.gray(resolvedEmail)}`);
17578
17654
  }
17579
17655
  if (a.address) {
17580
17656
  output.log(` Address: ${chalk59.gray(a.address)}`);
@@ -17644,7 +17720,13 @@ var EventSourceUpdateCommand = {
17644
17720
  describe: "是否启用",
17645
17721
  type: "boolean"
17646
17722
  }).option("address", {
17647
- describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host)",
17723
+ describe: "Agent IM 地址(bounty-im 类型用,格式:agent-id@host,v0.12 向后兼容)",
17724
+ type: "string"
17725
+ }).option("email", {
17726
+ describe: "Agent IM 注册邮箱(bounty-im 类型用,v0.13;与 --profile 互斥)",
17727
+ type: "string"
17728
+ }).option("profile", {
17729
+ describe: "Profile 名称(bounty-im 类型用,从 ~/.config/bounty/profiles/<name>.json 读取并自动更新 email + imServerUrl)",
17648
17730
  type: "string"
17649
17731
  }).option("tls-skip-verify", {
17650
17732
  describe: "跳过 TLS 证书校验(bounty-im 类型用,wss:// 自签名场景,生产环境不推荐)",
@@ -17679,6 +17761,25 @@ var EventSourceUpdateCommand = {
17679
17761
  }
17680
17762
  process.exit(1);
17681
17763
  }
17764
+ if (match.source.type === "bounty-im" && a.email && a.profile) {
17765
+ output.error(chalk60.red(`
17766
+ ✗ --email 和 --profile 互斥(profile 文件已包含 email)。请选择其一。
17767
+ `));
17768
+ process.exit(1);
17769
+ }
17770
+ let profileEmail;
17771
+ let profileApiBase;
17772
+ if (a.profile && match.source.type === "bounty-im") {
17773
+ const profile = readBountyProfile(a.profile);
17774
+ if (!profile) {
17775
+ output.error(chalk60.red(`
17776
+ ✗ Profile '${a.profile}' 不存在或格式错误。期望路径:~/.config/bounty/profiles/${a.profile}.json
17777
+ `));
17778
+ process.exit(1);
17779
+ }
17780
+ profileEmail = profile.email;
17781
+ profileApiBase = profile.api_base;
17782
+ }
17682
17783
  const partial = {};
17683
17784
  if (a.name !== undefined)
17684
17785
  partial.name = a.name;
@@ -17697,10 +17798,18 @@ var EventSourceUpdateCommand = {
17697
17798
  partial.enabled = a.enabled;
17698
17799
  if (a.address !== undefined)
17699
17800
  partial.address = a.address;
17700
- if (a.serverUrl !== undefined || a.imServerUrl !== undefined) {
17801
+ if (a.email !== undefined)
17802
+ partial.email = a.email;
17803
+ if (profileEmail !== undefined)
17804
+ partial.email = profileEmail;
17805
+ if (a.serverUrl !== undefined || a.imServerUrl !== undefined || profileApiBase !== undefined) {
17701
17806
  const envUrl = process.env.BOUNTY_SERVER_URL;
17702
17807
  const fallback = envUrl || "http://localhost:8787";
17703
- partial.imServerUrl = resolveServerUrl(a.serverUrl ?? a.imServerUrl, fallback);
17808
+ if (a.serverUrl !== undefined || a.imServerUrl !== undefined) {
17809
+ partial.imServerUrl = resolveServerUrl(a.serverUrl ?? a.imServerUrl, fallback);
17810
+ } else if (profileApiBase !== undefined) {
17811
+ partial.imServerUrl = profileToWsUrl(profileApiBase);
17812
+ }
17704
17813
  }
17705
17814
  if (a.tlsSkipVerify !== undefined)
17706
17815
  partial.tlsSkipVerify = a.tlsSkipVerify === true;
@@ -19146,6 +19255,121 @@ class DecoratorNodeValidator extends BaseNodeValidator {
19146
19255
  }
19147
19256
  }
19148
19257
 
19258
+ // src/commands/workflow/validators/nodes/python-call-node-validator.ts
19259
+ class PythonCallNodeValidator extends BaseNodeValidator {
19260
+ nodeType = "python_call";
19261
+ getRequiredFields() {
19262
+ return ["module", "function"];
19263
+ }
19264
+ validateTypeSpecific(node) {
19265
+ const errors = [];
19266
+ const config = node.config ?? {};
19267
+ const moduleVal = config.module;
19268
+ if (moduleVal === undefined || moduleVal === null) {
19269
+ errors.push({
19270
+ type: "MISSING_REQUIRED_FIELD" /* MISSING_REQUIRED_FIELD */,
19271
+ description: 'Field "module" is required for python_call node',
19272
+ expected: 'module: "<python.module.path>"',
19273
+ actual: "undefined",
19274
+ fix: 'Add `module: "<python.module.path>"` to the node config',
19275
+ nodeId: node.id
19276
+ });
19277
+ } else if (typeof moduleVal !== "string") {
19278
+ errors.push({
19279
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19280
+ description: 'Field "module" has invalid type',
19281
+ expected: 'string (Python module path, e.g. "investment_strategy.scripts.market_timing")',
19282
+ actual: typeof moduleVal,
19283
+ fix: "Change `module` to a string",
19284
+ nodeId: node.id
19285
+ });
19286
+ } else if (!/^[A-Za-z_]\w*(\.[A-Za-z_]\w*)*$/.test(moduleVal)) {
19287
+ errors.push({
19288
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19289
+ description: `Field "module" is not a valid Python module path: "${moduleVal}"`,
19290
+ expected: 'dotted identifier like "pkg.sub.mod"',
19291
+ actual: moduleVal,
19292
+ fix: "Use only letters, digits, underscores, and dots",
19293
+ nodeId: node.id
19294
+ });
19295
+ }
19296
+ const fnVal = config.function;
19297
+ if (fnVal === undefined || fnVal === null) {
19298
+ errors.push({
19299
+ type: "MISSING_REQUIRED_FIELD" /* MISSING_REQUIRED_FIELD */,
19300
+ description: 'Field "function" is required for python_call node',
19301
+ expected: 'function: "<python_function_name>"',
19302
+ actual: "undefined",
19303
+ fix: 'Add `function: "<name>"` to the node config',
19304
+ nodeId: node.id
19305
+ });
19306
+ } else if (typeof fnVal !== "string") {
19307
+ errors.push({
19308
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19309
+ description: 'Field "function" has invalid type',
19310
+ expected: 'string (Python function name, e.g. "run")',
19311
+ actual: typeof fnVal,
19312
+ fix: "Change `function` to a string",
19313
+ nodeId: node.id
19314
+ });
19315
+ } else if (!/^[A-Za-z_]\w*$/.test(fnVal)) {
19316
+ errors.push({
19317
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19318
+ description: `Field "function" is not a valid Python identifier: "${fnVal}"`,
19319
+ expected: "Python identifier: starts with letter/underscore, contains only [A-Za-z0-9_]",
19320
+ actual: fnVal,
19321
+ fix: "Use a plain Python function name (no dots, no operators)",
19322
+ nodeId: node.id
19323
+ });
19324
+ }
19325
+ const argsVal = config.args;
19326
+ if (argsVal !== undefined && (typeof argsVal !== "object" || argsVal === null || Array.isArray(argsVal))) {
19327
+ errors.push({
19328
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19329
+ description: 'Field "args" has invalid type',
19330
+ expected: "object (kwargs to pass to the function)",
19331
+ actual: Array.isArray(argsVal) ? "array" : typeof argsVal,
19332
+ fix: "Change `args` to an object: args: { key: value }",
19333
+ nodeId: node.id
19334
+ });
19335
+ }
19336
+ if (config.cwd !== undefined && typeof config.cwd !== "string") {
19337
+ errors.push({
19338
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19339
+ description: 'Field "cwd" has invalid type',
19340
+ expected: "string (filesystem path)",
19341
+ actual: typeof config.cwd,
19342
+ fix: "Change `cwd` to a string",
19343
+ nodeId: node.id
19344
+ });
19345
+ }
19346
+ if (config.python !== undefined && typeof config.python !== "string") {
19347
+ errors.push({
19348
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19349
+ description: 'Field "python" has invalid type',
19350
+ expected: "string (path to python interpreter)",
19351
+ actual: typeof config.python,
19352
+ fix: "Change `python` to a string",
19353
+ nodeId: node.id
19354
+ });
19355
+ }
19356
+ if (config.timeout !== undefined) {
19357
+ const t = config.timeout;
19358
+ if (typeof t !== "number" || !Number.isFinite(t) || t <= 0) {
19359
+ errors.push({
19360
+ type: "INVALID_FIELD_TYPE" /* INVALID_FIELD_TYPE */,
19361
+ description: 'Field "timeout" has invalid type',
19362
+ expected: "positive number (milliseconds)",
19363
+ actual: typeof t === "number" ? `${t}` : typeof t,
19364
+ fix: "Change `timeout` to a positive number, e.g. timeout: 60000",
19365
+ nodeId: node.id
19366
+ });
19367
+ }
19368
+ }
19369
+ return errors;
19370
+ }
19371
+ }
19372
+
19149
19373
  // src/commands/workflow/validators/node-validator-factory.ts
19150
19374
  var validators = new Map;
19151
19375
  validators.set("tool", new ToolNodeValidator);
@@ -19155,6 +19379,7 @@ validators.set("workflow", new WorkflowNodeValidator);
19155
19379
  validators.set("condition", new ConditionNodeValidator);
19156
19380
  validators.set("merge", new MergeNodeValidator);
19157
19381
  validators.set("decorator", new DecoratorNodeValidator);
19382
+ validators.set("python_call", new PythonCallNodeValidator);
19158
19383
  function getNodeValidator(type) {
19159
19384
  return validators.get(type) || null;
19160
19385
  }
@@ -20879,7 +21104,7 @@ Use `) + chalk74.cyan("roy-agent workflow nodes <type>") + chalk74.gray(" for de
20879
21104
 
20880
21105
  // src/commands/workflow/commands/validate.ts
20881
21106
  import chalk75 from "chalk";
20882
- import { readFileSync } from "fs";
21107
+ import { readFileSync as readFileSync2 } from "fs";
20883
21108
  async function parseWorkflowInput(input, yamlStr) {
20884
21109
  const parseYaml = async (content) => {
20885
21110
  const YAML2 = await Promise.resolve().then(() => __toESM(require_dist(), 1));
@@ -20887,7 +21112,7 @@ async function parseWorkflowInput(input, yamlStr) {
20887
21112
  };
20888
21113
  if (input && !yamlStr) {
20889
21114
  try {
20890
- const content = readFileSync(input, "utf-8");
21115
+ const content = readFileSync2(input, "utf-8");
20891
21116
  return await parseYaml(content);
20892
21117
  } catch (error) {
20893
21118
  throw new Error(`Failed to read file "${input}": ${error.message}`);
@@ -21622,24 +21847,24 @@ var LspCommand = {
21622
21847
 
21623
21848
  // src/commands/install/index.ts
21624
21849
  import { spawnSync } from "node:child_process";
21625
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync, mkdirSync, cpSync } from "node:fs";
21626
- import { join as join4, resolve } from "node:path";
21627
- import { homedir as homedir3 } from "node:os";
21850
+ import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync, mkdirSync, cpSync } from "node:fs";
21851
+ import { join as join5, resolve } from "node:path";
21852
+ import { homedir as homedir4 } from "node:os";
21628
21853
  function getConfigDir(scope) {
21629
- return scope === "global" ? join4(homedir3(), ".roy-agent") : join4(process.cwd(), ".roy");
21854
+ return scope === "global" ? join5(homedir4(), ".roy-agent") : join5(process.cwd(), ".roy");
21630
21855
  }
21631
21856
  function detectDefaultScope() {
21632
- const projectDir = join4(process.cwd(), ".roy");
21633
- return existsSync3(projectDir) ? "project" : "global";
21857
+ const projectDir = join5(process.cwd(), ".roy");
21858
+ return existsSync4(projectDir) ? "project" : "global";
21634
21859
  }
21635
21860
  function getConfigPath(scope) {
21636
- return join4(getConfigDir(scope), "plugins.json");
21861
+ return join5(getConfigDir(scope), "plugins.json");
21637
21862
  }
21638
21863
  function loadPlugins(scope) {
21639
21864
  const configPath = getConfigPath(scope);
21640
21865
  try {
21641
- if (existsSync3(configPath)) {
21642
- const raw = readFileSync2(configPath, "utf-8");
21866
+ if (existsSync4(configPath)) {
21867
+ const raw = readFileSync3(configPath, "utf-8");
21643
21868
  const config = JSON.parse(raw);
21644
21869
  return config.plugins ?? [];
21645
21870
  }
@@ -21649,7 +21874,7 @@ function loadPlugins(scope) {
21649
21874
  function savePlugins(plugins, scope) {
21650
21875
  const configDir = getConfigDir(scope);
21651
21876
  const configPath = getConfigPath(scope);
21652
- if (!existsSync3(configDir)) {
21877
+ if (!existsSync4(configDir)) {
21653
21878
  mkdirSync(configDir, { recursive: true });
21654
21879
  }
21655
21880
  const config = { plugins };
@@ -21665,10 +21890,10 @@ function stripVersionSpec(packageName) {
21665
21890
  function readPackageInfo(packageName) {
21666
21891
  const bareName = packageName.startsWith("/") || packageName.startsWith(".") ? packageName : stripVersionSpec(packageName);
21667
21892
  if (packageName.startsWith("/") || packageName.startsWith(".")) {
21668
- const localPkgPath = join4(packageName, "package.json");
21669
- if (existsSync3(localPkgPath)) {
21893
+ const localPkgPath = join5(packageName, "package.json");
21894
+ if (existsSync4(localPkgPath)) {
21670
21895
  try {
21671
- const pkg = JSON.parse(readFileSync2(localPkgPath, "utf-8"));
21896
+ const pkg = JSON.parse(readFileSync3(localPkgPath, "utf-8"));
21672
21897
  return {
21673
21898
  version: pkg.version ?? "0.0.0",
21674
21899
  name: pkg.name ?? packageName,
@@ -21680,19 +21905,19 @@ function readPackageInfo(packageName) {
21680
21905
  }
21681
21906
  }
21682
21907
  const searchPaths = [
21683
- join4(process.cwd(), "node_modules", bareName, "package.json"),
21908
+ join5(process.cwd(), "node_modules", bareName, "package.json"),
21684
21909
  resolve(process.cwd(), "..", "node_modules", bareName, "package.json"),
21685
- join4(process.cwd(), ".roy", "plugins", bareName, "package.json"),
21686
- join4(homedir3(), ".roy-agent", "node_modules", bareName, "package.json"),
21910
+ join5(process.cwd(), ".roy", "plugins", bareName, "package.json"),
21911
+ join5(homedir4(), ".roy-agent", "node_modules", bareName, "package.json"),
21687
21912
  ...(() => {
21688
21913
  const globalRoot = getNpmGlobalRoot();
21689
- return globalRoot ? [join4(globalRoot, bareName, "package.json")] : [];
21914
+ return globalRoot ? [join5(globalRoot, bareName, "package.json")] : [];
21690
21915
  })()
21691
21916
  ];
21692
21917
  for (const pkgPath of searchPaths) {
21693
21918
  try {
21694
- if (existsSync3(pkgPath)) {
21695
- const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
21919
+ if (existsSync4(pkgPath)) {
21920
+ const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
21696
21921
  return {
21697
21922
  version: pkg.version ?? "0.0.0",
21698
21923
  name: pkg.name ?? bareName,
@@ -21715,15 +21940,15 @@ function getNpmGlobalRoot() {
21715
21940
  return null;
21716
21941
  }
21717
21942
  function getPackageManagerCommand() {
21718
- if (existsSync3(join4(process.cwd(), "pnpm-lock.yaml"))) {
21719
- if (existsSync3(join4(process.cwd(), "pnpm-workspace.yaml"))) {
21943
+ if (existsSync4(join5(process.cwd(), "pnpm-lock.yaml"))) {
21944
+ if (existsSync4(join5(process.cwd(), "pnpm-workspace.yaml"))) {
21720
21945
  return "pnpm -w";
21721
21946
  }
21722
21947
  return "pnpm";
21723
21948
  }
21724
- if (existsSync3(join4(process.cwd(), "yarn.lock")))
21949
+ if (existsSync4(join5(process.cwd(), "yarn.lock")))
21725
21950
  return "yarn";
21726
- if (existsSync3(join4(process.cwd(), "bun.lock")) || existsSync3(join4(process.cwd(), "bun.lockb")))
21951
+ if (existsSync4(join5(process.cwd(), "bun.lock")) || existsSync4(join5(process.cwd(), "bun.lockb")))
21727
21952
  return "bun";
21728
21953
  return "npm";
21729
21954
  }
@@ -21762,14 +21987,14 @@ var InstallPackageCommand = {
21762
21987
  }
21763
21988
  resolvedName = info2.name;
21764
21989
  const srcDir = resolve(packageName);
21765
- if (!existsSync3(srcDir)) {
21990
+ if (!existsSync4(srcDir)) {
21766
21991
  console.error(`
21767
21992
  ❌ Local path '${srcDir}' does not exist.
21768
21993
  `);
21769
21994
  process.exit(1);
21770
21995
  }
21771
- const pluginDir = join4(process.cwd(), ".roy", "plugins", resolvedName);
21772
- if (!existsSync3(pluginDir)) {
21996
+ const pluginDir = join5(process.cwd(), ".roy", "plugins", resolvedName);
21997
+ if (!existsSync4(pluginDir)) {
21773
21998
  mkdirSync(pluginDir, { recursive: true });
21774
21999
  }
21775
22000
  const result = spawnSync("cp", ["-r", `${srcDir}/.`, pluginDir], {
@@ -21804,12 +22029,12 @@ var InstallPackageCommand = {
21804
22029
  process.exit(1);
21805
22030
  }
21806
22031
  resolvedName = info2.name;
21807
- const pluginDir = join4(process.cwd(), ".roy", "plugins", resolvedName);
21808
- if (!existsSync3(pluginDir)) {
22032
+ const pluginDir = join5(process.cwd(), ".roy", "plugins", resolvedName);
22033
+ if (!existsSync4(pluginDir)) {
21809
22034
  mkdirSync(pluginDir, { recursive: true });
21810
22035
  }
21811
- const nmPath = join4(process.cwd(), "node_modules", packageName);
21812
- if (existsSync3(nmPath)) {
22036
+ const nmPath = join5(process.cwd(), "node_modules", packageName);
22037
+ if (existsSync4(nmPath)) {
21813
22038
  spawnSync("cp", ["-r", `${nmPath}/.`, pluginDir], { stdio: "inherit", shell: false });
21814
22039
  }
21815
22040
  }
@@ -21840,14 +22065,14 @@ var InstallPackageCommand = {
21840
22065
  `);
21841
22066
  process.exit(1);
21842
22067
  }
21843
- const globalNm = join4(homedir3(), ".roy-agent", "node_modules", resolvedGlobalName);
21844
- if (!existsSync3(globalNm)) {
21845
- mkdirSync(join4(homedir3(), ".roy-agent", "node_modules"), { recursive: true });
22068
+ const globalNm = join5(homedir4(), ".roy-agent", "node_modules", resolvedGlobalName);
22069
+ if (!existsSync4(globalNm)) {
22070
+ mkdirSync(join5(homedir4(), ".roy-agent", "node_modules"), { recursive: true });
21846
22071
  const rootResult = spawnSync("npm", ["root", "-g"], { stdio: "pipe", shell: false });
21847
22072
  const globalRoot = rootResult.stdout?.toString().trim();
21848
22073
  if (globalRoot) {
21849
- const globalInstalled = join4(globalRoot, resolvedGlobalName);
21850
- if (existsSync3(globalInstalled)) {
22074
+ const globalInstalled = join5(globalRoot, resolvedGlobalName);
22075
+ if (existsSync4(globalInstalled)) {
21851
22076
  cpSync(globalInstalled, globalNm, { recursive: true });
21852
22077
  }
21853
22078
  }
@@ -21958,8 +22183,8 @@ var InstallRemoveCommand = {
21958
22183
  \uD83D\uDDD1️ Removing plugin: ${plugin.packageName}@${plugin.version} (${scope})
21959
22184
  `);
21960
22185
  if (scope === "project") {
21961
- const pluginDir = join4(process.cwd(), ".roy", "plugins", plugin.packageName);
21962
- if (existsSync3(pluginDir)) {
22186
+ const pluginDir = join5(process.cwd(), ".roy", "plugins", plugin.packageName);
22187
+ if (existsSync4(pluginDir)) {
21963
22188
  spawnSync("rm", ["-rf", pluginDir], { stdio: "inherit", shell: false });
21964
22189
  console.log(` Removed plugin directory: ${pluginDir}`);
21965
22190
  }
@@ -21974,8 +22199,8 @@ var InstallRemoveCommand = {
21974
22199
  `);
21975
22200
  process.exit(result.status ?? 1);
21976
22201
  }
21977
- const globalNm = join4(homedir3(), ".roy-agent", "node_modules", plugin.packageName);
21978
- if (existsSync3(globalNm)) {
22202
+ const globalNm = join5(homedir4(), ".roy-agent", "node_modules", plugin.packageName);
22203
+ if (existsSync4(globalNm)) {
21979
22204
  spawnSync("rm", ["-rf", globalNm], { stdio: "inherit", shell: false });
21980
22205
  }
21981
22206
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-cli",
3
- "version": "1.6.6",
3
+ "version": "1.6.7",
4
4
  "type": "module",
5
5
  "description": "CLI for roy-agent - Non-interactive command execution",
6
6
  "main": "./dist/index.js",