oh-my-opencode-cohub 1.0.19 → 1.2.0

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.
@@ -1,3 +1,5 @@
1
+ import type { ContextConfig } from '../context/types';
2
+ import { DEFAULT_CONTEXT_CONFIG } from '../context/types';
1
3
  /** 单个 councillor 配置 */
2
4
  export interface CouncillorConfig {
3
5
  model: string;
@@ -23,9 +25,11 @@ export interface AgentOverride {
23
25
  export interface CoHubConfig {
24
26
  agents?: Record<string, AgentOverride>;
25
27
  council?: CouncilConfig;
28
+ context?: Partial<ContextConfig>;
26
29
  }
27
30
  /** 加载用户配置 */
28
31
  export declare function loadCoHubConfig(): CoHubConfig;
29
32
  /** 示例配置模板 */
30
33
  export declare const DEFAULT_CONFIG: CoHubConfig;
34
+ export { DEFAULT_CONTEXT_CONFIG };
31
35
  //# sourceMappingURL=loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAIA,uBAAuB;AACvB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yBAAyB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,oBAAoB;AACpB,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAKD,aAAa;AACb,wBAAgB,eAAe,IAAI,WAAW,CAQ7C;AAED,aAAa;AACb,eAAO,MAAM,cAAc,EAAE,WAe5B,CAAC"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,uBAAuB;AACvB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yBAAyB,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;IAClD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,oBAAoB;AACpB,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACvC,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CAClC;AAKD,aAAa;AACb,wBAAgB,eAAe,IAAI,WAAW,CAQ7C;AAED,aAAa;AACb,eAAO,MAAM,cAAc,EAAE,WAe5B,CAAC;AAEF,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,50 @@
1
+ import type { ContextStrategy, ContextConfig } from './types';
2
+ import type { createOpencodeClient } from '@opencode-ai/sdk';
3
+ type SdkClient = ReturnType<typeof createOpencodeClient>;
4
+ export declare class ContextEngine {
5
+ /** contextId → TaskContext */
6
+ private registry;
7
+ /** alias → 前置子代理结果 */
8
+ private dependencyCache;
9
+ private client;
10
+ private config;
11
+ constructor(client: SdkClient, config?: Partial<ContextConfig>);
12
+ /**
13
+ * 同步注册上下文占位并返回 contextId。
14
+ * 标记可立即注入到 output.args.description。
15
+ */
16
+ registerContext(args: {
17
+ description: string;
18
+ }): string;
19
+ /**
20
+ * 异步填充已注册的上下文(不阻塞工具启动)。
21
+ */
22
+ fillContextAsync(contextId: string, parentSessionId: string, args: {
23
+ strategy: ContextStrategy;
24
+ }): Promise<void>;
25
+ /**
26
+ * Phase B: 消费标记文本。
27
+ * 从消息文本中提取 contextId → 查 registry → 替换标记为格式化上下文。
28
+ * 返回替换后的完整文本,或 null(无标记或未找到上下文)。
29
+ */
30
+ consumeMarkedContext(messageText: string): string | null;
31
+ /**
32
+ * Phase C: 捕获子代理结果。
33
+ * 读取子 session 的最终输出 → 提取关键信息 → 存入 dependencyCache。
34
+ */
35
+ captureResult(childSessionId: string, alias: string, agent: string): Promise<void>;
36
+ /**
37
+ * 生成上下文标记文本,追加到 task description 末尾。
38
+ */
39
+ formatMarker(contextId: string): string;
40
+ /**
41
+ * 暴露合并后的 strategy 供 index.ts 使用
42
+ */
43
+ getStrategy(agentType: string): ContextStrategy;
44
+ /**
45
+ * 清理过期的依赖缓存(超过 10 分钟的条目)。
46
+ */
47
+ cleanupStaleDependencies(maxAgeMs?: number): void;
48
+ }
49
+ export {};
50
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/context/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAe,aAAa,EAAoB,MAAM,SAAS,CAAC;AAI7F,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEzD,qBAAa,aAAa;IACxB,8BAA8B;IAC9B,OAAO,CAAC,QAAQ,CAAkC;IAClD,sBAAsB;IACtB,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAU9D;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAYtD;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE;QAAE,QAAQ,EAAE,eAAe,CAAA;KAAE,GAClC,OAAO,CAAC,IAAI,CAAC;IAgChB;;;;OAIG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAiBxD;;;OAGG;IACG,aAAa,CACjB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC;IAuChB;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAIvC;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe;IAI/C;;OAEG;IACH,wBAAwB,CAAC,QAAQ,GAAE,MAAuB,GAAG,IAAI;CAQlE"}
@@ -0,0 +1,30 @@
1
+ import type { RelevantFile } from './types';
2
+ /** SDK v2 消息格式(简化) */
3
+ interface SdkMessage {
4
+ info?: {
5
+ role?: string;
6
+ };
7
+ parts?: Array<{
8
+ type?: string;
9
+ text?: string;
10
+ tool?: string;
11
+ args?: unknown;
12
+ tool_result?: unknown;
13
+ }>;
14
+ }
15
+ /**
16
+ * 从消息列表中提取相关文件。
17
+ * 扫描 Read/Edit/Write/Glob/Grep 工具调用和 tool_result 中的路径。
18
+ */
19
+ export declare function extractRelevantFiles(messages: SdkMessage[], maxFiles: number, windowSize: number): RelevantFile[];
20
+ /**
21
+ * 从 assistant 消息中提取关键决策。
22
+ * 匹配包含决策关键词的句子。
23
+ */
24
+ export declare function extractDecisions(messages: SdkMessage[], maxDecisions: number, windowSize: number): string[];
25
+ /**
26
+ * 从 bash 输出中提取编译/测试错误。
27
+ */
28
+ export declare function extractErrors(messages: SdkMessage[], maxErrors: number, windowSize: number): string[];
29
+ export {};
30
+ //# sourceMappingURL=extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/context/extractor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,sBAAsB;AACtB,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACvG;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EAAE,EACtB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,YAAY,EAAE,CAwChB;AAUD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,UAAU,EAAE,EACtB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAqBV;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,UAAU,EAAE,EACtB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAsBV"}
@@ -0,0 +1,15 @@
1
+ import type { TaskContext } from './types';
2
+ /** 上下文标记正则 — 用于在 messages.transform 中匹配 */
3
+ export declare const CONTEXT_MARKER_PATTERN: RegExp;
4
+ /** 生成上下文标记文本 */
5
+ export declare function formatContextMarker(contextId: string): string;
6
+ /**
7
+ * 将 TaskContext 格式化为注入到子代理 user 消息中的 Markdown 块。
8
+ */
9
+ export declare function formatTaskContext(context: TaskContext): string;
10
+ /**
11
+ * 将标记替换为格式化的上下文块。
12
+ * 返回替换后的完整消息文本,或 null(如果未找到标记)。
13
+ */
14
+ export declare function replaceMarkerWithContext(messageText: string, context: TaskContext): string | null;
15
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/context/formatter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,2CAA2C;AAC3C,eAAO,MAAM,sBAAsB,QAAqC,CAAC;AAEzE,gBAAgB;AAChB,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAiD9D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAMjG"}
@@ -0,0 +1,7 @@
1
+ import type { ContextStrategy } from './types';
2
+ /**
3
+ * 解析子代理的上下文策略。
4
+ * 优先级:task 覆盖参数 > 代理默认配置 > 'none'
5
+ */
6
+ export declare function resolveStrategy(agentType: string, defaults: Record<string, ContextStrategy>, override?: ContextStrategy): ContextStrategy;
7
+ //# sourceMappingURL=strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../../src/context/strategy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,EACzC,QAAQ,CAAC,EAAE,eAAe,GACzB,eAAe,CAGjB"}
@@ -0,0 +1,45 @@
1
+ /** 上下文注入策略 */
2
+ export type ContextStrategy = 'none' | 'relevant' | 'summary' | 'full';
3
+ /** 任务相关文件描述 */
4
+ export interface RelevantFile {
5
+ path: string;
6
+ lines?: string;
7
+ summary: string;
8
+ }
9
+ /** 前置子代理的完成结果 */
10
+ export interface DependencyResult {
11
+ alias: string;
12
+ agent: string;
13
+ keyOutput: string;
14
+ capturedAt: number;
15
+ }
16
+ /** 注入到子代理的结构化上下文 */
17
+ export interface TaskContext {
18
+ goal: string;
19
+ relevantFiles: RelevantFile[];
20
+ decisions: string[];
21
+ errors: string[];
22
+ dependencies: DependencyResult[];
23
+ }
24
+ /** 上下文系统配置 */
25
+ export interface ContextConfig {
26
+ /** 各代理的默认上下文策略 */
27
+ strategy: Record<string, ContextStrategy>;
28
+ /** 最多注入多少个相关文件 */
29
+ maxFiles: number;
30
+ /** 最多注入多少条决策 */
31
+ maxDecisions: number;
32
+ /** 最多注入多少条错误 */
33
+ maxErrors: number;
34
+ /** 最多注入多少条依赖结果 */
35
+ maxDependencies: number;
36
+ /** 是否启用依赖传播(子代理结果自动注入到后续子代理) */
37
+ dependencyPropagation: boolean;
38
+ /** LLM 摘要最大 token 数 */
39
+ summarizeMaxTokens: number;
40
+ /** 从父 session 中扫描最近多少条消息 */
41
+ relevantMessageWindow: number;
42
+ }
43
+ /** 默认配置 */
44
+ export declare const DEFAULT_CONTEXT_CONFIG: ContextConfig;
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/context/types.ts"],"names":[],"mappings":"AAEA,cAAc;AACd,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvE,eAAe;AACf,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iBAAiB;AACjB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,oBAAoB;AACpB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,cAAc;AACd,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC1C,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uBAAuB;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4BAA4B;IAC5B,qBAAqB,EAAE,MAAM,CAAC;CAC/B;AAED,WAAW;AACX,eAAO,MAAM,sBAAsB,EAAE,aAqBpC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAsClD,wBAAwB;AACxB,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAalD,CAAC;AAwEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,wrBAA+B,CAAC;AAEhE,QAAA,MAAM,WAAW,EAAE,MA6SlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAyClD,wBAAwB;AACxB,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAalD,CAAC;AAwEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,wrBAA+B,CAAC;AAEhE,QAAA,MAAM,WAAW,EAAE,MAgXlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -468,6 +468,7 @@ class TaskTracker {
468
468
  jobs = new Map;
469
469
  counters = new Map;
470
470
  _currentParentSessionId = "";
471
+ _reconciledForParent = "";
471
472
  get currentParentSessionId() {
472
473
  return this._currentParentSessionId;
473
474
  }
@@ -479,6 +480,14 @@ class TaskTracker {
479
480
  }
480
481
  registerBeforeTask(parentSessionId, args) {
481
482
  this._currentParentSessionId = parentSessionId;
483
+ if (this._reconciledForParent !== parentSessionId) {
484
+ this._reconciledForParent = parentSessionId;
485
+ for (const job of this.jobs.values()) {
486
+ if (job.parentSessionId === parentSessionId && job.status !== "running") {
487
+ job.terminalReconciled = true;
488
+ }
489
+ }
490
+ }
482
491
  const agent = args.subagent_type ?? "unknown";
483
492
  const alias = this.alias(agent);
484
493
  const label = typeof args.description === "string" ? args.description : alias;
@@ -598,6 +607,324 @@ class TaskTracker {
598
607
  }
599
608
  return count;
600
609
  }
610
+ getJobBySessionId(sessionId) {
611
+ for (const job of this.jobs.values()) {
612
+ if (job.sessionId === sessionId) {
613
+ return { alias: job.alias, agent: job.agent };
614
+ }
615
+ }
616
+ return;
617
+ }
618
+ markCancelled(taskId) {
619
+ let job = this.jobs.get(taskId);
620
+ if (!job) {
621
+ for (const j of this.jobs.values()) {
622
+ if (j.sessionId === taskId) {
623
+ job = j;
624
+ break;
625
+ }
626
+ }
627
+ }
628
+ if (job) {
629
+ job.status = "cancelled";
630
+ job.terminalReconciled = true;
631
+ }
632
+ }
633
+ }
634
+
635
+ // src/context/types.ts
636
+ var DEFAULT_CONTEXT_CONFIG = {
637
+ strategy: {
638
+ "co-explorer": "none",
639
+ "co-librarian": "none",
640
+ "co-observer": "none",
641
+ "co-fixer": "relevant",
642
+ "co-designer": "relevant",
643
+ "co-planner": "relevant",
644
+ "co-oracle": "summary",
645
+ "co-council": "summary",
646
+ "co-rule-user": "none",
647
+ "co-rule-project": "none",
648
+ "co-rule-app": "none"
649
+ },
650
+ maxFiles: 5,
651
+ maxDecisions: 10,
652
+ maxErrors: 5,
653
+ maxDependencies: 8,
654
+ dependencyPropagation: true,
655
+ summarizeMaxTokens: 2000,
656
+ relevantMessageWindow: 20
657
+ };
658
+
659
+ // src/context/extractor.ts
660
+ function extractRelevantFiles(messages, maxFiles, windowSize) {
661
+ const recent = messages.slice(-windowSize);
662
+ const fileMap = new Map;
663
+ for (const msg of recent) {
664
+ for (const part of msg.parts ?? []) {
665
+ if (part.type === "tool_call" && part.args) {
666
+ const args = part.args;
667
+ const path = extractPath(args);
668
+ if (path && !fileMap.has(path)) {
669
+ fileMap.set(path, { path, summary: "" });
670
+ }
671
+ }
672
+ if (part.type === "tool_result" && part.tool_result) {
673
+ const tr = part.tool_result;
674
+ const path = extractPath(tr);
675
+ if (path && fileMap.has(path)) {
676
+ const existing = fileMap.get(path);
677
+ const args = tr.args;
678
+ if (args) {
679
+ if (typeof args.offset === "number") {
680
+ const limit = typeof args.limit === "number" ? args.limit : 50;
681
+ existing.lines = `${args.offset}-${args.offset + limit}`;
682
+ }
683
+ if (typeof args.oldString === "string") {
684
+ existing.summary = `编辑位置: ${args.oldString.slice(0, 80)}`;
685
+ }
686
+ }
687
+ if (!existing.summary && typeof tr.output === "string") {
688
+ existing.summary = tr.output.slice(0, 100).replace(/\n/g, " ");
689
+ }
690
+ }
691
+ }
692
+ }
693
+ }
694
+ return Array.from(fileMap.values()).slice(0, maxFiles);
695
+ }
696
+ function extractPath(obj) {
697
+ if (typeof obj.filePath === "string")
698
+ return obj.filePath;
699
+ if (typeof obj.path === "string")
700
+ return obj.path;
701
+ if (typeof obj.file === "string")
702
+ return obj.file;
703
+ if (typeof obj.filepath === "string")
704
+ return obj.filepath;
705
+ return;
706
+ }
707
+ function extractDecisions(messages, maxDecisions, windowSize) {
708
+ const recent = messages.slice(-windowSize);
709
+ const decisions = [];
710
+ const keywords = /(认定|决定|确认|方案是|结论|应该|不建议|必须|禁止|采用)/;
711
+ for (const msg of recent) {
712
+ if (msg.info?.role !== "assistant")
713
+ continue;
714
+ for (const part of msg.parts ?? []) {
715
+ if (part.type !== "text" || !part.text)
716
+ continue;
717
+ const sentences = part.text.split(/[。!?\n]/);
718
+ for (const s of sentences) {
719
+ const trimmed = s.trim();
720
+ if (trimmed.length > 10 && trimmed.length < 200 && keywords.test(trimmed)) {
721
+ decisions.push(trimmed);
722
+ if (decisions.length >= maxDecisions)
723
+ return decisions;
724
+ }
725
+ }
726
+ }
727
+ }
728
+ return decisions;
729
+ }
730
+ function extractErrors(messages, maxErrors, windowSize) {
731
+ const recent = messages.slice(-windowSize);
732
+ const errors = [];
733
+ const errorPatterns = /(error|Error|TypeError|ReferenceError|SyntaxError|RangeError|FAIL|failed|cannot find|cannot resolve|not found|unexpected token)/;
734
+ for (const msg of recent) {
735
+ for (const part of msg.parts ?? []) {
736
+ if (part.type !== "tool_result" || !part.tool_result)
737
+ continue;
738
+ const tr = part.tool_result;
739
+ const output = typeof tr.output === "string" ? tr.output : "";
740
+ if (!output)
741
+ continue;
742
+ const lines = output.split(`
743
+ `);
744
+ for (const line of lines) {
745
+ if (errorPatterns.test(line) && line.length < 300) {
746
+ errors.push(line.trim());
747
+ if (errors.length >= maxErrors)
748
+ return errors;
749
+ }
750
+ }
751
+ }
752
+ }
753
+ return errors;
754
+ }
755
+
756
+ // src/context/formatter.ts
757
+ var CONTEXT_MARKER_PATTERN = /<!-- CONTEXT:ID=([a-f0-9-]+) -->/;
758
+ function formatContextMarker(contextId) {
759
+ return `
760
+
761
+ <!-- CONTEXT:ID=${contextId} -->`;
762
+ }
763
+ function formatTaskContext(context) {
764
+ const lines = [];
765
+ lines.push("");
766
+ lines.push("### \uD83D\uDCCB 任务上下文 (CoHub 自动注入)");
767
+ lines.push("");
768
+ if (context.goal) {
769
+ lines.push(`**当前任务**: ${context.goal}`);
770
+ lines.push("");
771
+ }
772
+ if (context.relevantFiles.length > 0) {
773
+ lines.push("**相关文件**:");
774
+ lines.push("| 文件 | 说明 |");
775
+ lines.push("|------|------|");
776
+ for (const f of context.relevantFiles) {
777
+ const loc = f.lines ? `:${f.lines}` : "";
778
+ lines.push(`| \`${f.path}${loc}\` | ${f.summary || "-"} |`);
779
+ }
780
+ lines.push("");
781
+ }
782
+ if (context.decisions.length > 0) {
783
+ lines.push("**前置决策**:");
784
+ for (let i = 0;i < context.decisions.length; i++) {
785
+ lines.push(`${i + 1}. ${context.decisions[i]}`);
786
+ }
787
+ lines.push("");
788
+ }
789
+ if (context.dependencies.length > 0) {
790
+ lines.push("**依赖结果**:");
791
+ for (const d of context.dependencies) {
792
+ lines.push(`- \`${d.alias}\` (${d.agent}): ${d.keyOutput}`);
793
+ }
794
+ lines.push("");
795
+ }
796
+ if (context.errors.length > 0) {
797
+ lines.push("**错误信息**:");
798
+ for (const e of context.errors) {
799
+ lines.push(`- \`${e}\``);
800
+ }
801
+ lines.push("");
802
+ }
803
+ lines.push("<!-- CONTEXT:END -->");
804
+ return lines.join(`
805
+ `);
806
+ }
807
+ function replaceMarkerWithContext(messageText, context) {
808
+ const match = messageText.match(CONTEXT_MARKER_PATTERN);
809
+ if (!match)
810
+ return null;
811
+ const formatted = formatTaskContext(context);
812
+ return messageText.replace(CONTEXT_MARKER_PATTERN, formatted);
813
+ }
814
+
815
+ // src/context/engine.ts
816
+ class ContextEngine {
817
+ registry = new Map;
818
+ dependencyCache = new Map;
819
+ client;
820
+ config;
821
+ constructor(client, config) {
822
+ this.client = client;
823
+ this.config = {
824
+ ...DEFAULT_CONTEXT_CONFIG,
825
+ ...config,
826
+ strategy: { ...DEFAULT_CONTEXT_CONFIG.strategy, ...config?.strategy }
827
+ };
828
+ }
829
+ registerContext(args) {
830
+ const contextId = crypto.randomUUID();
831
+ this.registry.set(contextId, {
832
+ goal: args.description,
833
+ relevantFiles: [],
834
+ decisions: [],
835
+ errors: [],
836
+ dependencies: []
837
+ });
838
+ return contextId;
839
+ }
840
+ async fillContextAsync(contextId, parentSessionId, args) {
841
+ const context = this.registry.get(contextId);
842
+ if (!context)
843
+ return;
844
+ if (args.strategy === "none")
845
+ return;
846
+ try {
847
+ const windowSize = this.config.relevantMessageWindow;
848
+ const messagesResult = await this.client.session.messages({
849
+ path: { id: parentSessionId },
850
+ query: { limit: windowSize }
851
+ });
852
+ const messages = messagesResult.data ?? [];
853
+ if (args.strategy === "relevant" || args.strategy === "summary" || args.strategy === "full") {
854
+ context.relevantFiles = extractRelevantFiles(messages, this.config.maxFiles, windowSize);
855
+ context.decisions = extractDecisions(messages, this.config.maxDecisions, windowSize);
856
+ context.errors = extractErrors(messages, this.config.maxErrors, windowSize);
857
+ }
858
+ if (this.config.dependencyPropagation && this.dependencyCache.size > 0) {
859
+ context.dependencies = Array.from(this.dependencyCache.values()).slice(-this.config.maxDependencies);
860
+ }
861
+ } catch {}
862
+ }
863
+ consumeMarkedContext(messageText) {
864
+ const markerMatch = messageText.match(CONTEXT_MARKER_PATTERN);
865
+ if (!markerMatch)
866
+ return null;
867
+ const contextId = markerMatch[1];
868
+ const context = this.registry.get(contextId);
869
+ if (!context) {
870
+ return messageText.replace(CONTEXT_MARKER_PATTERN, "");
871
+ }
872
+ const result = replaceMarkerWithContext(messageText, context);
873
+ this.registry.delete(contextId);
874
+ return result;
875
+ }
876
+ async captureResult(childSessionId, alias, agent) {
877
+ if (!this.config.dependencyPropagation)
878
+ return;
879
+ try {
880
+ const messagesResult = await this.client.session.messages({
881
+ path: { id: childSessionId }
882
+ });
883
+ const messages = messagesResult.data ?? [];
884
+ let keyOutput = "";
885
+ for (let i = messages.length - 1;i >= 0; i--) {
886
+ if (messages[i].info?.role === "assistant") {
887
+ for (const part of messages[i].parts ?? []) {
888
+ if (part.type === "text" && part.text) {
889
+ keyOutput = part.text.slice(0, 500).replace(/\n/g, " ");
890
+ break;
891
+ }
892
+ }
893
+ if (keyOutput)
894
+ break;
895
+ }
896
+ }
897
+ if (keyOutput) {
898
+ this.dependencyCache.set(alias, {
899
+ alias,
900
+ agent,
901
+ keyOutput,
902
+ capturedAt: Date.now()
903
+ });
904
+ }
905
+ } catch {}
906
+ }
907
+ formatMarker(contextId) {
908
+ return formatContextMarker(contextId);
909
+ }
910
+ getStrategy(agentType) {
911
+ return this.config.strategy[agentType] ?? "none";
912
+ }
913
+ cleanupStaleDependencies(maxAgeMs = 10 * 60 * 1000) {
914
+ const now = Date.now();
915
+ for (const [key, value] of this.dependencyCache) {
916
+ if (now - value.capturedAt > maxAgeMs) {
917
+ this.dependencyCache.delete(key);
918
+ }
919
+ }
920
+ }
921
+ }
922
+
923
+ // src/context/strategy.ts
924
+ function resolveStrategy(agentType, defaults, override) {
925
+ if (override)
926
+ return override;
927
+ return defaults[agentType] ?? "none";
601
928
  }
602
929
 
603
930
  // src/config/loader.ts
@@ -1154,6 +1481,8 @@ var CoHubPlugin = async (input, options) => {
1154
1481
  }
1155
1482
  }
1156
1483
  };
1484
+ const contextConfig = userConfig.context ?? {};
1485
+ const contextEngine = new ContextEngine(input.client, contextConfig);
1157
1486
  const councilConfig = userConfig.council ?? DEFAULT_COUNCIL_CONFIG;
1158
1487
  const councilManager = new CouncilManager(input.client, input.directory, councilConfig);
1159
1488
  const councilTools = createCouncilTool(input, councilManager);
@@ -1198,6 +1527,11 @@ var CoHubPlugin = async (input, options) => {
1198
1527
  tracker.cleanupStaleJobs(STALE_TIMEOUT_MS);
1199
1528
  } catch {}
1200
1529
  }, 30000);
1530
+ const contextCleanupTimer = setInterval(() => {
1531
+ try {
1532
+ contextEngine.cleanupStaleDependencies();
1533
+ } catch {}
1534
+ }, 60000);
1201
1535
  const agentConfigs = {};
1202
1536
  for (const agent of agents) {
1203
1537
  agentConfigs[agent.name] = {
@@ -1224,18 +1558,39 @@ var CoHubPlugin = async (input, options) => {
1224
1558
  try {
1225
1559
  if (input2.tool === "task") {
1226
1560
  const args = output.args ?? {};
1561
+ const subagentType = typeof args.subagent_type === "string" ? args.subagent_type : undefined;
1562
+ const description = typeof args.description === "string" ? args.description : "";
1227
1563
  tracker.registerBeforeTask(input2.sessionID, {
1228
- description: typeof args.description === "string" ? args.description : undefined,
1229
- subagent_type: typeof args.subagent_type === "string" ? args.subagent_type : undefined,
1564
+ description,
1565
+ subagent_type: subagentType,
1230
1566
  task_id: typeof args.task_id === "string" ? args.task_id : undefined,
1231
1567
  background: typeof args.background === "boolean" ? args.background : undefined
1232
1568
  });
1233
1569
  syncTrackerState(input2.sessionID ?? "");
1570
+ if (subagentType) {
1571
+ const strategy = resolveStrategy(subagentType, contextEngine.getStrategy(subagentType) !== undefined ? { [subagentType]: contextEngine.getStrategy(subagentType) } : contextConfig.strategy ?? {}, typeof args.context_override === "string" ? args.context_override : undefined);
1572
+ if (strategy !== "none") {
1573
+ const contextId = contextEngine.registerContext({
1574
+ description
1575
+ });
1576
+ output.args.description = description + contextEngine.formatMarker(contextId);
1577
+ contextEngine.fillContextAsync(contextId, input2.sessionID, {
1578
+ strategy
1579
+ }).catch(() => {});
1580
+ }
1581
+ }
1234
1582
  }
1235
1583
  } catch {}
1236
1584
  },
1237
1585
  "tool.execute.after": async (input2, output) => {
1238
1586
  try {
1587
+ if (input2.tool === "cancel_task") {
1588
+ const args = input2.args;
1589
+ const taskId = args?.task_id;
1590
+ if (typeof taskId === "string")
1591
+ tracker.markCancelled(taskId);
1592
+ syncTrackerState(input2.sessionID ?? "");
1593
+ }
1239
1594
  if (input2.tool === "task") {
1240
1595
  const childSessionId = extractChildSessionId(output);
1241
1596
  tracker.updateAfterTask(input2.sessionID, "completed", childSessionId);
@@ -1252,6 +1607,10 @@ var CoHubPlugin = async (input, options) => {
1252
1607
  if (e.type === "session.idle") {
1253
1608
  tracker.updateByChildSessionId(sessionId, "completed");
1254
1609
  syncTrackerState(tracker.currentParentSessionId);
1610
+ const job = tracker.getJobBySessionId(sessionId);
1611
+ if (job) {
1612
+ contextEngine.captureResult(sessionId, job.alias, job.agent);
1613
+ }
1255
1614
  } else if (e.type === "session.deleted" || e.type === "session.error") {
1256
1615
  tracker.updateByChildSessionId(sessionId, "errored");
1257
1616
  syncTrackerState(tracker.currentParentSessionId);
@@ -1260,6 +1619,20 @@ var CoHubPlugin = async (input, options) => {
1260
1619
  },
1261
1620
  "experimental.chat.messages.transform": async (_input, output) => {
1262
1621
  try {
1622
+ if (output.messages && Array.isArray(output.messages)) {
1623
+ for (const msg of output.messages) {
1624
+ if (msg.info.role !== "user")
1625
+ continue;
1626
+ for (const part of msg.parts ?? []) {
1627
+ if (part.type !== "text" || !part.text)
1628
+ continue;
1629
+ const replaced = contextEngine.consumeMarkedContext(part.text);
1630
+ if (replaced !== null) {
1631
+ part.text = replaced;
1632
+ }
1633
+ }
1634
+ }
1635
+ }
1263
1636
  const board = tracker.getBoardText();
1264
1637
  if (board && output.messages && Array.isArray(output.messages)) {
1265
1638
  for (let i = output.messages.length - 1;i >= 0; i--) {
@@ -1285,6 +1658,7 @@ var CoHubPlugin = async (input, options) => {
1285
1658
  },
1286
1659
  dispose: async () => {
1287
1660
  clearInterval(cleanupTimer);
1661
+ clearInterval(contextCleanupTimer);
1288
1662
  }
1289
1663
  };
1290
1664
  };
@@ -4,6 +4,8 @@ export declare class TaskTracker {
4
4
  private counters;
5
5
  /** 最近一次 tool hook 收到的 parentSessionId */
6
6
  private _currentParentSessionId;
7
+ /** 已 reconcile 的父 session ID,避免同一轮重复 reconcile */
8
+ private _reconciledForParent;
7
9
  get currentParentSessionId(): string;
8
10
  /** 生成代理别名,如 fixer → "fix-1", explorer → "exp-2" */
9
11
  private alias;
@@ -41,5 +43,12 @@ export declare class TaskTracker {
41
43
  getRunningAgents(parentSessionId: string): string[];
42
44
  /** 获取父会话下所有运行中的任务数量 */
43
45
  getRunningCount(parentSessionId: string): number;
46
+ /** 根据子 session ID 查找 JobRecord */
47
+ getJobBySessionId(sessionId: string): {
48
+ alias: string;
49
+ agent: string;
50
+ } | undefined;
51
+ /** cancel_task 集成:根据别名或 sessionId 标记任务为已取消并 reconcile */
52
+ markCancelled(taskId: string): void;
44
53
  }
45
54
  //# sourceMappingURL=tracker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/task-manager/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/D,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAgC;IAC5C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,yCAAyC;IACzC,OAAO,CAAC,uBAAuB,CAAM;IAErC,IAAI,sBAAsB,IAAI,MAAM,CAEnC;IAED,mDAAmD;IACnD,OAAO,CAAC,KAAK;IAOb;;OAEG;IACH,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM;IAqBnE;;;OAGG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAwBtF;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IASnE;;OAEG;IACH,YAAY,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA4CrD;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOjC;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IASzC;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAKlC,2BAA2B;IAC3B,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE;IAUnD,uBAAuB;IACvB,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM;CASjD"}
1
+ {"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/task-manager/tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE/D,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAgC;IAC5C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,yCAAyC;IACzC,OAAO,CAAC,uBAAuB,CAAM;IACrC,kDAAkD;IAClD,OAAO,CAAC,oBAAoB,CAAM;IAElC,IAAI,sBAAsB,IAAI,MAAM,CAEnC;IAED,mDAAmD;IACnD,OAAO,CAAC,KAAK;IAOb;;OAEG;IACH,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM;IA8BnE;;;OAGG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IAwBtF;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IASnE;;OAEG;IACH,YAAY,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IA4CrD;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOjC;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IASzC;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAKlC,2BAA2B;IAC3B,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE;IAUnD,uBAAuB;IACvB,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM;IAUhD,kCAAkC;IAClC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IASlF,yDAAyD;IACzD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAYpC"}
@@ -1,3 +1,4 @@
1
+ import type { ContextStrategy } from '../context/types';
1
2
  export type TaskStatus = 'running' | 'completed' | 'errored' | 'cancelled';
2
3
  export interface JobRecord {
3
4
  alias: string;
@@ -9,6 +10,10 @@ export interface JobRecord {
9
10
  background: boolean;
10
11
  terminalReconciled: boolean;
11
12
  createdAt: number;
13
+ /** 此子代理的上下文策略 */
14
+ contextStrategy?: ContextStrategy;
15
+ /** 依赖的前置任务别名列表 */
16
+ dependencies?: string[];
12
17
  }
13
18
  export interface TaskArgs {
14
19
  description?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/task-manager/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,CAAC;AAE3E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/task-manager/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,WAAW,CAAC;AAE3E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB;IACjB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,kBAAkB;IAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode-cohub",
3
- "version": "1.0.19",
3
+ "version": "1.2.0",
4
4
  "description": "OpenCode 中文智能体编排插件 CoHub - 纯调度模式 / 全中文提示词 / 规范分析代理 / 方案制定代理 / 独立运行",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",