agency-orchestrator 0.6.12 → 0.6.14

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/dist/cli.js CHANGED
@@ -433,10 +433,12 @@ async function handleInit() {
433
433
  if (cfgModel)
434
434
  updates.AO_MODEL = cfgModel;
435
435
  if (cfgBaseUrl) {
436
- // Route to the env var the matching connector already reads
436
+ // Route to the env var the matching connector already reads.
437
+ // 每个 provider 写到自己专属的 BASE_URL env,避免 issue #16 的跨污染
437
438
  const p = (cfgProvider || '').toLowerCase();
438
439
  const urlVar = p === 'ollama' ? 'OLLAMA_BASE_URL' :
439
- 'OPENAI_BASE_URL';
440
+ p === 'deepseek' ? 'DEEPSEEK_BASE_URL' :
441
+ 'OPENAI_BASE_URL';
440
442
  updates[urlVar] = cfgBaseUrl;
441
443
  }
442
444
  if (cfgApiKey) {
@@ -28,9 +28,11 @@ export function createConnector(config) {
28
28
  case 'claude':
29
29
  return new ClaudeConnector(config.api_key);
30
30
  case 'deepseek':
31
+ // 不 fallback OPENAI_BASE_URL — issue #16: 用户设了 OPENAI_BASE_URL=openai.com 后切到
32
+ // deepseek 会用 OpenAI endpoint + DeepSeek key 调,得到 405。每个 provider 用自己专属 env
31
33
  return new OpenAICompatibleConnector({
32
34
  apiKey: config.api_key || process.env.DEEPSEEK_API_KEY,
33
- baseUrl: config.base_url || process.env.OPENAI_BASE_URL || 'https://api.deepseek.com/v1',
35
+ baseUrl: config.base_url || process.env.DEEPSEEK_BASE_URL || 'https://api.deepseek.com/v1',
34
36
  });
35
37
  case 'openai':
36
38
  return new OpenAICompatibleConnector({
@@ -7,7 +7,8 @@
7
7
  import type { LLMConnector, LLMResult, LLMConfig } from '../types.js';
8
8
  export declare class OpenAICompatibleConnector implements LLMConnector {
9
9
  private apiKey;
10
- private baseUrl;
10
+ /** 只读暴露给外部 debug / 测试用,运行时不可变 */
11
+ readonly baseUrl: string;
11
12
  constructor(options?: {
12
13
  apiKey?: string;
13
14
  baseUrl?: string;
@@ -11,6 +11,7 @@ function estimateTokens(text) {
11
11
  }
12
12
  export class OpenAICompatibleConnector {
13
13
  apiKey;
14
+ /** 只读暴露给外部 debug / 测试用,运行时不可变 */
14
15
  baseUrl;
15
16
  constructor(options = {}) {
16
17
  this.apiKey = options.apiKey || process.env.OPENAI_API_KEY || '';
@@ -65,6 +65,12 @@ export function validateWorkflow(workflow) {
65
65
  const stepById = new Map(workflow.steps.map(s => [s.id, s]));
66
66
  // step.output 唯一性检查:两个 step 不能 output 到同一个变量名
67
67
  // 否则下游引用拿到的值取决于 context Map 的写入顺序,不可预期
68
+ //
69
+ // 两类合法例外不报错:
70
+ // 1. any_completed 分支收敛:下游用 depends_on_mode: any_completed 引用这些
71
+ // 重名 step(任一分支完成即走,重名 output 是有意设计)
72
+ // 2. loop 迭代覆盖:重名 step 中有任一个带 loop 字段(种子 step + loop step
73
+ // 反复覆盖同名 output,是常见的"原地修改"迭代模式,如 write/revise/brand_review 链)
68
74
  const outputToSteps = new Map();
69
75
  for (const step of workflow.steps) {
70
76
  if (!step.output)
@@ -74,9 +80,17 @@ export function validateWorkflow(workflow) {
74
80
  outputToSteps.set(step.output, owners);
75
81
  }
76
82
  for (const [outName, owners] of outputToSteps) {
77
- if (owners.length > 1) {
78
- errors.push(`output 变量 "${outName}" 被多个 step 同时产出: ${owners.join(', ')}(重名会让下游引用结果不确定)`);
79
- }
83
+ if (owners.length <= 1)
84
+ continue;
85
+ const ownerSet = new Set(owners);
86
+ const hasAnyCompletedConsumer = workflow.steps.some(s => s.depends_on_mode === 'any_completed'
87
+ && s.depends_on?.some(d => ownerSet.has(d)));
88
+ if (hasAnyCompletedConsumer)
89
+ continue;
90
+ const hasLoopOwner = owners.some(id => stepById.get(id)?.loop);
91
+ if (hasLoopOwner)
92
+ continue;
93
+ errors.push(`output 变量 "${outName}" 被多个 step 同时产出: ${owners.join(', ')}(重名会让下游引用结果不确定)`);
80
94
  }
81
95
  // 计算每个 step 的 DAG 上游 step ids(递归 depends_on 闭包,不含自身)。
82
96
  // 用于校验"变量必须来自 inputs 或当前 step 的上游"——和 autoFix 的拓扑约束保持一致
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agency-orchestrator",
3
- "version": "0.6.12",
3
+ "version": "0.6.14",
4
4
  "description": "Multi-agent YAML workflow engine — 211 AI roles, auto DAG parallelism, zero code. One sentence → multiple AI roles collaborate → complete plan in minutes. 10 LLM providers, 7 need no API key.",
5
5
  "keywords": [
6
6
  "multi-agent",
@@ -64,7 +64,7 @@
64
64
  "scripts": {
65
65
  "build": "tsc",
66
66
  "dev": "tsc --watch",
67
- "test": "npx tsx test/run.ts && npx tsx test/condition.ts && npx tsx test/cli.ts && npx tsx test/compose.ts && npx tsx test/demo.ts && npx tsx test/e2e.ts && npx tsx test/e2e-condition.ts && npx tsx test/e2e-loop.ts && npx tsx test/mcp.ts",
67
+ "test": "npx tsx test/run.ts && npx tsx test/condition.ts && npx tsx test/cli.ts && npx tsx test/compose.ts && npx tsx test/demo.ts && npx tsx test/factory-custom.ts && npx tsx test/step-llm.ts && npx tsx test/step-llm-yaml.ts && npx tsx test/stdin-limit.ts && npx tsx test/compose-name.ts && npx tsx test/e2e.ts && npx tsx test/e2e-condition.ts && npx tsx test/e2e-loop.ts && npx tsx test/mcp.ts",
68
68
  "prepublishOnly": "npm run build"
69
69
  },
70
70
  "files": [
@@ -87,7 +87,7 @@ steps:
87
87
 
88
88
  每条风险明确标「发生概率」(高/中/低)。
89
89
  output: risk
90
- depends_on: [research]
90
+ depends_on: [research, financial]
91
91
 
92
92
  - id: cfo_opinion
93
93
  role: "finance/finance-financial-forecaster"
@@ -97,7 +97,7 @@ steps:
97
97
 
98
98
  ⚠️ 所有法条引用不确定处必须明确标「需核实最新法规」。
99
99
  output: risk_analysis
100
- depends_on: [intake]
100
+ depends_on: [intake, document_review]
101
101
 
102
102
  - id: opinion
103
103
  role: "legal/legal-policy-writer"
@@ -81,7 +81,7 @@ steps:
81
81
 
82
82
  风格参考:小红书当前热门的视觉趋势。
83
83
  output: visual_plan
84
- depends_on: [topic_planning]
84
+ depends_on: [topic_planning, write_notes]
85
85
 
86
86
  - id: optimize
87
87
  role: "marketing/marketing-xiaohongshu-operator"