@router-agent/runtime 0.0.0-stage → 0.3.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/agents/claude.d.ts +51 -0
  2. package/dist/agents/claude.js +270 -0
  3. package/dist/agents/claude.js.map +1 -0
  4. package/dist/agents/codex.d.ts +36 -0
  5. package/dist/agents/codex.js +292 -0
  6. package/dist/agents/codex.js.map +1 -0
  7. package/dist/agents/profile.d.ts +39 -0
  8. package/dist/agents/profile.js +2 -0
  9. package/dist/agents/profile.js.map +1 -0
  10. package/dist/agents/registry.d.ts +21 -0
  11. package/dist/agents/registry.js +78 -0
  12. package/dist/agents/registry.js.map +1 -0
  13. package/dist/errors.d.ts +4 -0
  14. package/dist/errors.js +9 -0
  15. package/dist/errors.js.map +1 -0
  16. package/dist/evidence-gate.d.ts +78 -0
  17. package/dist/evidence-gate.js +196 -0
  18. package/dist/evidence-gate.js.map +1 -0
  19. package/dist/index.d.ts +22 -0
  20. package/dist/index.js +21 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/naming.d.ts +23 -0
  23. package/dist/naming.js +40 -0
  24. package/dist/naming.js.map +1 -0
  25. package/dist/permissions/acp.d.ts +21 -0
  26. package/dist/permissions/acp.js +73 -0
  27. package/dist/permissions/acp.js.map +1 -0
  28. package/dist/permissions.d.ts +1 -0
  29. package/dist/permissions.js +2 -0
  30. package/dist/permissions.js.map +1 -0
  31. package/dist/plugins/loader.d.ts +46 -0
  32. package/dist/plugins/loader.js +117 -0
  33. package/dist/plugins/loader.js.map +1 -0
  34. package/dist/plugins/types.d.ts +52 -0
  35. package/dist/plugins/types.js +2 -0
  36. package/dist/plugins/types.js.map +1 -0
  37. package/dist/port.d.ts +295 -0
  38. package/dist/port.js +17 -0
  39. package/dist/port.js.map +1 -0
  40. package/dist/registry.d.ts +13 -0
  41. package/dist/registry.js +35 -0
  42. package/dist/registry.js.map +1 -0
  43. package/dist/report-poller.d.ts +58 -0
  44. package/dist/report-poller.js +130 -0
  45. package/dist/report-poller.js.map +1 -0
  46. package/dist/resume.d.ts +52 -0
  47. package/dist/resume.js +109 -0
  48. package/dist/resume.js.map +1 -0
  49. package/dist/runtimes/acp-agents.d.ts +85 -0
  50. package/dist/runtimes/acp-agents.js +167 -0
  51. package/dist/runtimes/acp-agents.js.map +1 -0
  52. package/dist/runtimes/acp-detect-utils.d.ts +4 -0
  53. package/dist/runtimes/acp-detect-utils.js +35 -0
  54. package/dist/runtimes/acp-detect-utils.js.map +1 -0
  55. package/dist/runtimes/builtin-options.d.ts +3 -0
  56. package/dist/runtimes/builtin-options.js +44 -0
  57. package/dist/runtimes/builtin-options.js.map +1 -0
  58. package/dist/runtimes/catalog.d.ts +31 -0
  59. package/dist/runtimes/catalog.js +75 -0
  60. package/dist/runtimes/catalog.js.map +1 -0
  61. package/dist/runtimes/options.d.ts +60 -0
  62. package/dist/runtimes/options.js +89 -0
  63. package/dist/runtimes/options.js.map +1 -0
  64. package/dist/spec/contract.md +120 -0
  65. package/dist/spec/index.d.ts +35 -0
  66. package/dist/spec/index.js +59 -0
  67. package/dist/spec/index.js.map +1 -0
  68. package/dist/spec/prompt-mode.md +176 -0
  69. package/dist/spec/reader.d.ts +5 -0
  70. package/dist/spec/reader.js +32 -0
  71. package/dist/spec/reader.js.map +1 -0
  72. package/dist/status.d.ts +8 -0
  73. package/dist/status.js +22 -0
  74. package/dist/status.js.map +1 -0
  75. package/dist/workspaces/git-worktree.d.ts +44 -0
  76. package/dist/workspaces/git-worktree.js +183 -0
  77. package/dist/workspaces/git-worktree.js.map +1 -0
  78. package/dist/workspaces/overview.d.ts +66 -0
  79. package/dist/workspaces/overview.js +12 -0
  80. package/dist/workspaces/overview.js.map +1 -0
  81. package/package.json +36 -4
  82. package/README.md +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acp-agents.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/runtimes/acp-agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** 在 PATH 里解析命令;支持 Windows 的 PATHEXT。返回绝对路径。 */
2
+ export declare function resolveExecutable(command: string, env: NodeJS.ProcessEnv): string | undefined;
3
+ /** 从 `--version` 输出里提取 x.y.z;找不到返回 undefined。 */
4
+ export declare function parseVersion(text: string): string | undefined;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * 运行时共用的可执行文件解析与版本提取(纯函数,不 spawn)。
3
+ * ACP 插件与其它运行时插件都从这里取同一份语义。
4
+ */
5
+ import { existsSync } from 'node:fs';
6
+ import { delimiter, isAbsolute, join } from 'node:path';
7
+ /** 在 PATH 里解析命令;支持 Windows 的 PATHEXT。返回绝对路径。 */
8
+ export function resolveExecutable(command, env) {
9
+ const value = command.trim();
10
+ if (!value)
11
+ return undefined;
12
+ if (isAbsolute(value) || value.includes('/') || value.includes('\\')) {
13
+ return existsSync(value) ? value : undefined;
14
+ }
15
+ const pathValue = env.PATH ?? env.Path ?? '';
16
+ const extensions = process.platform === 'win32'
17
+ ? ['', '.cmd', '.exe', '.bat']
18
+ : [''];
19
+ for (const dir of pathValue.split(delimiter)) {
20
+ if (!dir)
21
+ continue;
22
+ for (const ext of extensions) {
23
+ const candidate = join(dir, `${value}${ext}`);
24
+ if (existsSync(candidate))
25
+ return candidate;
26
+ }
27
+ }
28
+ return undefined;
29
+ }
30
+ /** 从 `--version` 输出里提取 x.y.z;找不到返回 undefined。 */
31
+ export function parseVersion(text) {
32
+ const match = /(\d+\.\d+\.\d+(?:[-+][\w.-]+)?)/.exec(text);
33
+ return match?.[1];
34
+ }
35
+ //# sourceMappingURL=acp-detect-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acp-detect-utils.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/runtimes/acp-detect-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEvD,gDAAgD;AAChD,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,GAAsB;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAC5B,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAC5B,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACrE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;IAC9C,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAA;IAC5C,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO;QAC7C,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QAC9B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACR,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,GAAG;YAAE,SAAQ;QAClB,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GAAG,EAAE,CAAC,CAAA;YAC7C,IAAI,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAA;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,KAAK,GAAG,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1D,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAA;AACnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RuntimeOptionSpec } from './options.js';
2
+ export declare const ORCA_OPTION_SPEC: RuntimeOptionSpec;
3
+ export declare const HERDR_OPTION_SPEC: RuntimeOptionSpec;
@@ -0,0 +1,44 @@
1
+ export const ORCA_OPTION_SPEC = {
2
+ runtimeId: 'orca',
3
+ fields: [
4
+ {
5
+ key: 'agent',
6
+ label: '执行 Agent',
7
+ kind: 'select',
8
+ default: 'claude',
9
+ options: [
10
+ { value: 'claude', label: 'claude · Claude Code' },
11
+ { value: 'codex', label: 'codex · Codex' },
12
+ { value: 'opencode', label: 'opencode · OpenCode' },
13
+ { value: 'devin', label: 'devin · Devin' },
14
+ { value: 'antigravity', label: 'antigravity · Antigravity' },
15
+ ],
16
+ hint: 'Orca 在工单 worktree 里启动哪个 Agent;默认 Claude Code',
17
+ },
18
+ ],
19
+ };
20
+ export const HERDR_OPTION_SPEC = {
21
+ runtimeId: 'herdr',
22
+ fields: [
23
+ {
24
+ key: 'agent',
25
+ label: '执行 Agent',
26
+ kind: 'select',
27
+ default: 'claude',
28
+ options: [
29
+ { value: 'claude', label: 'claude · Claude Code' },
30
+ { value: 'codex', label: 'codex · Codex' },
31
+ { value: 'opencode', label: 'opencode · OpenCode' },
32
+ ],
33
+ hint: 'Herdr 在工单 worktree 里启动哪个 Agent;默认 Claude Code',
34
+ },
35
+ {
36
+ key: 'model',
37
+ label: '模型',
38
+ kind: 'text',
39
+ placeholder: '留空则用 Agent 自己的默认模型',
40
+ hint: '传给 Agent 的模型名;不同 Agent 的参数名由 adapter 自己映射',
41
+ },
42
+ ],
43
+ };
44
+ //# sourceMappingURL=builtin-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin-options.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/runtimes/builtin-options.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,gBAAgB,GAAsB;IACjD,SAAS,EAAE,MAAM;IACjB,MAAM,EAAE;QACN;YACE,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,UAAU;YACjB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,sBAAsB,EAAE;gBAClD,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE;gBAC1C,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,qBAAqB,EAAE;gBACnD,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE;gBAC1C,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,2BAA2B,EAAE;aAC7D;YACD,IAAI,EAAE,8CAA8C;SACrD;KACF;CACF,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IAClD,SAAS,EAAE,OAAO;IAClB,MAAM,EAAE;QACN;YACE,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,UAAU;YACjB,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE;gBACP,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,sBAAsB,EAAE;gBAClD,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE;gBAC1C,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,qBAAqB,EAAE;aACpD;YACD,IAAI,EAAE,+CAA+C;SACtD;QACD;YACE,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,IAAI;YACX,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,oBAAoB;YACjC,IAAI,EAAE,2CAA2C;SAClD;KACF;CACF,CAAA"}
@@ -0,0 +1,31 @@
1
+ export declare const ORCA_RUNTIME_ID = "orca";
2
+ export declare const CLAUDE_CODE_RUNTIME_ID = "claude-code";
3
+ export declare const ACP_RUNTIME_ID = "acp";
4
+ export declare const CODEX_APP_RUNTIME_ID = "codex-app";
5
+ export declare const HERDR_RUNTIME_ID = "herdr";
6
+ export interface WorkerRuntimeMeta {
7
+ id: string;
8
+ /** 产品名(自然大小写);Web 面板按首字母大写展示,CLI 与文档保持原样。 */
9
+ name: string;
10
+ label: string;
11
+ hint: string;
12
+ /** 不能由 ra 自动安装时的界面引导文案。 */
13
+ installHint?: string;
14
+ /** CLI 的官方安装/下载页;Web 卡片直接跳转,不再展示易变的安装命令。 */
15
+ installUrl?: string;
16
+ }
17
+ export declare const WORKER_RUNTIMES: readonly WorkerRuntimeMeta[];
18
+ export declare const WORKER_RUNTIME_IDS: readonly string[];
19
+ /** 兼容旧配置与旧工单:claude-cli 已改名为 claude-code。 */
20
+ export declare const LEGACY_CLAUDE_CODE_RUNTIME_ID = "claude-cli";
21
+ export declare const LEGACY_RUNTIME_IDS: Readonly<Record<string, string>>;
22
+ /** 把历史 runtime id 归一成当前 id;未知 id 原样返回,交给注册表报错。 */
23
+ export declare function normalizeRuntimeId(id: string): string;
24
+ /**
25
+ * 是否是已知的 worker runtime id。
26
+ *
27
+ * 包含内置运行时(orca / claude-code / codex-app / acp)和 ACP 目录里的动态运行时
28
+ * (acp-claude / acp-codex / ...)。未知值让配置校验直接拒绝,避免拼错后
29
+ * 启动期才炸。
30
+ */
31
+ export declare function isWorkerRuntimeId(id: string): boolean;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Worker 运行时清单:配置校验、Web 面板下拉、CLI 提示共用这一份。
3
+ *
4
+ * 这里只放纯常量,不能依赖任何 Node 内置模块 —— Web 面板会把它一起打进前端包。
5
+ */
6
+ import { ACP_AGENTS } from './acp-agents.js';
7
+ export const ORCA_RUNTIME_ID = 'orca';
8
+ export const CLAUDE_CODE_RUNTIME_ID = 'claude-code';
9
+ export const ACP_RUNTIME_ID = 'acp';
10
+ export const CODEX_APP_RUNTIME_ID = 'codex-app';
11
+ export const HERDR_RUNTIME_ID = 'herdr';
12
+ export const WORKER_RUNTIMES = [
13
+ {
14
+ id: ORCA_RUNTIME_ID,
15
+ name: 'Orca',
16
+ label: 'orca · Orca worktree + 终端',
17
+ hint: '通过 Orca 创建 worktree 并启动 Agent 终端(默认跟随 Orca 配置),交互与状态读取走 Orca',
18
+ installHint: '从 Orca 官方发布页下载安装,并确保 orca CLI 在 PATH 中',
19
+ installUrl: 'https://github.com/stablyai/orca/releases',
20
+ },
21
+ {
22
+ id: CLAUDE_CODE_RUNTIME_ID,
23
+ name: 'Claude Code',
24
+ label: 'claude-code · git worktree + claude --bg',
25
+ hint: '直接调用 Claude Code CLI 的后台会话;项目 repo 需要填本地仓库绝对路径',
26
+ installHint: '参考 Claude Code 官方安装说明',
27
+ installUrl: 'https://docs.claude.com/en/docs/claude-code/setup',
28
+ },
29
+ {
30
+ id: CODEX_APP_RUNTIME_ID,
31
+ name: 'Codex App',
32
+ label: 'codex-app · Codex App Server',
33
+ hint: '直连 Codex App Server;优先使用 Codex App 内置 CLI,桌面端可见同一 thread',
34
+ installHint: '安装 Codex App(macOS/Windows)或 Codex CLI;ra 会优先使用 Codex App 内置的版本',
35
+ installUrl: 'https://chatgpt.com/codex',
36
+ },
37
+ {
38
+ id: ACP_RUNTIME_ID,
39
+ name: 'ACP',
40
+ label: 'acp · 任意 ACP Agent',
41
+ hint: '通过 ACP 协议接入其它 Agent;启用前需要在 runtime.options.acp 配置 command',
42
+ installHint: '在 config.yaml 的 runtime.options.acp 下配置 command 与 args,然后重启服务',
43
+ },
44
+ {
45
+ id: HERDR_RUNTIME_ID,
46
+ name: 'Herdr',
47
+ label: 'herdr · git worktree + Herdr 终端',
48
+ hint: '检出由 ra 用 git worktree 建,Herdr 只开终端窗口跑 Agent;状态来自 Herdr 的 Agent 检测',
49
+ installHint: '从 Herdr 官方发布页下载安装,并确保 herdr CLI 在 PATH 中',
50
+ installUrl: 'https://github.com/herdrdev/herdr/releases',
51
+ },
52
+ ];
53
+ export const WORKER_RUNTIME_IDS = WORKER_RUNTIMES.map(runtime => runtime.id);
54
+ /** 兼容旧配置与旧工单:claude-cli 已改名为 claude-code。 */
55
+ export const LEGACY_CLAUDE_CODE_RUNTIME_ID = 'claude-cli';
56
+ export const LEGACY_RUNTIME_IDS = {
57
+ [LEGACY_CLAUDE_CODE_RUNTIME_ID]: CLAUDE_CODE_RUNTIME_ID,
58
+ };
59
+ /** 把历史 runtime id 归一成当前 id;未知 id 原样返回,交给注册表报错。 */
60
+ export function normalizeRuntimeId(id) {
61
+ const value = id.trim();
62
+ return LEGACY_RUNTIME_IDS[value] ?? value;
63
+ }
64
+ /**
65
+ * 是否是已知的 worker runtime id。
66
+ *
67
+ * 包含内置运行时(orca / claude-code / codex-app / acp)和 ACP 目录里的动态运行时
68
+ * (acp-claude / acp-codex / ...)。未知值让配置校验直接拒绝,避免拼错后
69
+ * 启动期才炸。
70
+ */
71
+ export function isWorkerRuntimeId(id) {
72
+ const value = normalizeRuntimeId(id);
73
+ return WORKER_RUNTIME_IDS.includes(value) || ACP_AGENTS.some(agent => agent.runtimeId === value);
74
+ }
75
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/runtimes/catalog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAA;AACrC,MAAM,CAAC,MAAM,sBAAsB,GAAG,aAAa,CAAA;AACnD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAA;AACnC,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAA;AAC/C,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAA;AAcvC,MAAM,CAAC,MAAM,eAAe,GAAiC;IAC3D;QACE,EAAE,EAAE,eAAe;QACnB,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,2BAA2B;QAClC,IAAI,EAAE,8DAA8D;QACpE,WAAW,EAAE,wCAAwC;QACrD,UAAU,EAAE,2CAA2C;KACxD;IACD;QACE,EAAE,EAAE,sBAAsB;QAC1B,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,0CAA0C;QACjD,IAAI,EAAE,gDAAgD;QACtD,WAAW,EAAE,uBAAuB;QACpC,UAAU,EAAE,mDAAmD;KAChE;IACD;QACE,EAAE,EAAE,oBAAoB;QACxB,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,8BAA8B;QACrC,IAAI,EAAE,0DAA0D;QAChE,WAAW,EAAE,iEAAiE;QAC9E,UAAU,EAAE,2BAA2B;KACxC;IACD;QACE,EAAE,EAAE,cAAc;QAClB,IAAI,EAAE,KAAK;QACX,KAAK,EAAE,oBAAoB;QAC3B,IAAI,EAAE,2DAA2D;QACjE,WAAW,EAAE,+DAA+D;KAC7E;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,iCAAiC;QACxC,IAAI,EAAE,mEAAmE;QACzE,WAAW,EAAE,0CAA0C;QACvD,UAAU,EAAE,4CAA4C;KACzD;CACF,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAsB,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAE/F,6CAA6C;AAC7C,MAAM,CAAC,MAAM,6BAA6B,GAAG,YAAY,CAAA;AAEzD,MAAM,CAAC,MAAM,kBAAkB,GAAqC;IAClE,CAAC,6BAA6B,CAAC,EAAE,sBAAsB;CACxD,CAAA;AAED,kDAAkD;AAClD,MAAM,UAAU,kBAAkB,CAAC,EAAU;IAC3C,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA;IACvB,OAAO,kBAAkB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAA;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,MAAM,KAAK,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAA;IACpC,OAAO,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,CAAA;AAClG,CAAC"}
@@ -0,0 +1,60 @@
1
+ export { ORCA_OPTION_SPEC, HERDR_OPTION_SPEC } from './builtin-options.js';
2
+ export type RuntimeOptionKind = 'text' | 'select' | 'switch' | 'number';
3
+ export interface RuntimeOptionValue {
4
+ value: string;
5
+ label: string;
6
+ hint?: string;
7
+ }
8
+ export interface RuntimeOptionField {
9
+ /** 选项键;配置里对应 `runtime.options.<runtimeId>.<key>`。 */
10
+ key: string;
11
+ label: string;
12
+ kind: RuntimeOptionKind;
13
+ /**
14
+ * 未配置时的声明式默认值。
15
+ *
16
+ * 运行时与面板都从这里取值,避免「默认值」散落在 adapter、面板、文档三处。
17
+ * 有些工具的选项没有可省略的形态(例如 Orca 的 `--prompt` 必须配 `--agent`),
18
+ * 这种情况就靠这里给出一个真实默认值,而不是让调用方猜。
19
+ */
20
+ default?: string | number | boolean;
21
+ /** kind=select 时的候选取值。 */
22
+ options?: RuntimeOptionValue[];
23
+ placeholder?: string;
24
+ hint?: string;
25
+ /** kind=number 时的取值范围。 */
26
+ min?: number;
27
+ max?: number;
28
+ }
29
+ export interface RuntimeOptionSpec {
30
+ runtimeId: string;
31
+ fields: RuntimeOptionField[];
32
+ }
33
+ /** 所有运行时的选项声明;新增运行时在这里加一行即可。 */
34
+ export declare const RUNTIME_OPTION_SPECS: readonly RuntimeOptionSpec[];
35
+ export declare function optionSpecOf(runtimeId: string): RuntimeOptionSpec | null;
36
+ export declare function optionFieldOf(runtimeId: string, key: string): RuntimeOptionField | null;
37
+ /** 某个选项未配置时的声明式默认值;没有声明返回 undefined。 */
38
+ export declare function runtimeOptionDefault(runtimeId: string, key: string): unknown;
39
+ /** 配置里的点路径:runtime.options.<runtimeId>.<key>。 */
40
+ export declare function runtimeOptionPath(runtimeId: string, key: string): string;
41
+ /** 解析 `runtime.options.<runtimeId>.<key>`;不是这个形状返回 null。 */
42
+ export declare function parseRuntimeOptionPath(path: string): {
43
+ runtimeId: string;
44
+ key: string;
45
+ } | null;
46
+ /** 全部已声明的选项路径;面板据此判断「哪些配置被改过」。 */
47
+ export declare function runtimeOptionPaths(): string[];
48
+ /**
49
+ 从配置里取某个运行时的字符串选项。
50
+ *
51
+ * 运行时之间没有特例:调用方只需要知道「我要哪个运行时的哪个选项」。
52
+ * 没配置(或显式留空)时回落到声明里的默认值。
53
+ */
54
+ export declare function runtimeOptionString(options: Record<string, unknown> | undefined, runtimeId: string, key: string): string;
55
+ /**
56
+ * 校验一个选项值;合法返回 null,否则返回可直接展示给用户的错误文案。
57
+ *
58
+ * select 的候选取值里允许出现空串:它表示「不覆盖」,写入配置时应当删掉这个键。
59
+ */
60
+ export declare function validateRuntimeOption(field: RuntimeOptionField, value: unknown): string | null;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * 运行时选项:每个运行时自己声明「可以配什么」,面板按声明渲染、后端按声明校验。
3
+ *
4
+ * 这里只放纯类型与纯函数,不能依赖任何 Node 内置模块 —— Web 面板会把它一起打进前端包。
5
+ * 配置落点是通用的 `runtime.options.<runtimeId>.<key>`,新增运行时不需要改内核或面板。
6
+ */
7
+ import { ORCA_OPTION_SPEC, HERDR_OPTION_SPEC } from './builtin-options.js';
8
+ export { ORCA_OPTION_SPEC, HERDR_OPTION_SPEC } from './builtin-options.js';
9
+ /** 所有运行时的选项声明;新增运行时在这里加一行即可。 */
10
+ export const RUNTIME_OPTION_SPECS = [ORCA_OPTION_SPEC, HERDR_OPTION_SPEC];
11
+ export function optionSpecOf(runtimeId) {
12
+ return RUNTIME_OPTION_SPECS.find(spec => spec.runtimeId === runtimeId) ?? null;
13
+ }
14
+ export function optionFieldOf(runtimeId, key) {
15
+ return optionSpecOf(runtimeId)?.fields.find(field => field.key === key) ?? null;
16
+ }
17
+ /** 某个选项未配置时的声明式默认值;没有声明返回 undefined。 */
18
+ export function runtimeOptionDefault(runtimeId, key) {
19
+ return optionFieldOf(runtimeId, key)?.default;
20
+ }
21
+ /** 配置里的点路径:runtime.options.<runtimeId>.<key>。 */
22
+ export function runtimeOptionPath(runtimeId, key) {
23
+ return `runtime.options.${runtimeId}.${key}`;
24
+ }
25
+ /** 解析 `runtime.options.<runtimeId>.<key>`;不是这个形状返回 null。 */
26
+ export function parseRuntimeOptionPath(path) {
27
+ const match = /^runtime\.options\.([^.]+)\.([^.]+)$/.exec(path);
28
+ if (!match)
29
+ return null;
30
+ return { runtimeId: match[1], key: match[2] };
31
+ }
32
+ /** 全部已声明的选项路径;面板据此判断「哪些配置被改过」。 */
33
+ export function runtimeOptionPaths() {
34
+ return RUNTIME_OPTION_SPECS.flatMap(spec => spec.fields.map(field => runtimeOptionPath(spec.runtimeId, field.key)));
35
+ }
36
+ /**
37
+ 从配置里取某个运行时的字符串选项。
38
+ *
39
+ * 运行时之间没有特例:调用方只需要知道「我要哪个运行时的哪个选项」。
40
+ * 没配置(或显式留空)时回落到声明里的默认值。
41
+ */
42
+ export function runtimeOptionString(options, runtimeId, key) {
43
+ const entry = options?.[runtimeId];
44
+ if (entry && typeof entry === 'object' && !Array.isArray(entry)) {
45
+ const value = entry[key];
46
+ if (typeof value === 'string' && value.trim())
47
+ return value.trim();
48
+ }
49
+ const fallback = runtimeOptionDefault(runtimeId, key);
50
+ return typeof fallback === 'string' ? fallback.trim() : '';
51
+ }
52
+ /**
53
+ * 校验一个选项值;合法返回 null,否则返回可直接展示给用户的错误文案。
54
+ *
55
+ * select 的候选取值里允许出现空串:它表示「不覆盖」,写入配置时应当删掉这个键。
56
+ */
57
+ export function validateRuntimeOption(field, value) {
58
+ switch (field.kind) {
59
+ case 'select': {
60
+ const text = String(value ?? '').trim();
61
+ const allowed = field.options?.map(option => option.value) ?? [];
62
+ if (allowed.includes(text))
63
+ return null;
64
+ // 留空表示回到声明里的默认值;没声明默认值的选项仍然必须显式选择。
65
+ if (text === '' && field.default !== undefined)
66
+ return null;
67
+ return `取值必须是:${allowed.map(item => item || '(空)').join(' / ')}`;
68
+ }
69
+ case 'switch': {
70
+ if (typeof value === 'boolean')
71
+ return null;
72
+ const text = String(value ?? '').trim();
73
+ return text === 'true' || text === 'false' ? null : '取值必须是 true / false';
74
+ }
75
+ case 'number': {
76
+ const n = Number(value);
77
+ if (!Number.isInteger(n))
78
+ return '必须是整数';
79
+ if (field.min !== undefined && n < field.min)
80
+ return `不能小于 ${field.min}`;
81
+ if (field.max !== undefined && n > field.max)
82
+ return `不能大于 ${field.max}`;
83
+ return null;
84
+ }
85
+ default:
86
+ return typeof value === 'string' ? null : '必须是字符串';
87
+ }
88
+ }
89
+ //# sourceMappingURL=options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/runtimes/options.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ # Router Agent Worker 手册
2
+
3
+ 你是 router-agent 派出的 Worker,在一个独立的 git worktree 里工作,负责完成下面这张工单。
4
+ 你**只对 Router(编排层)负责**:所有状态通过 `ra report` 上报,不要直接给飞书发消息,不要自己联系发起人。
5
+
6
+ ## 工单
7
+
8
+ - 工单 ID:`{{ticketId}}`
9
+ - 标题:{{title}}
10
+ - 授权范围:{{scope}}
11
+ - 仓库:{{repo}}
12
+ - 起始分支:{{branch}}
13
+ - 工作分支:{{workBranch}}
14
+ - 工作目录:{{workdir}}
15
+
16
+ {{attachments}}
17
+
18
+ ## 先判断怎么回
19
+
20
+ | 产出 | 怎么交付 |
21
+ | --- | --- |
22
+ | 代码变更 | 开 PR(GitHub)或 MR(GitLab),`ra report` 带上 `--pr-number` / `--pr-url`,可附一段 `--reply` 说明;改 UI 时 PR / MR 描述必须附 Before / After 对比 |
23
+ | 分析、结论、答疑 | 把要发的话直接写进 `--reply` |
24
+ | 很长的结论 / 多章节 / 需要沉淀转发 | 先 `ra doc` 生成飞书文档,再把文档链接写进 `--reply` |
25
+
26
+ - **非代码类工单不要为了交付去改代码、跑构建或开 PR / MR**,也不要因为「没有 PR / MR」而卡住。
27
+ - GitHub 仓库用 `gh` 开 PR,GitLab 仓库用 `glab mr create` 开 MR;没有 `glab` 时可用 `git push -o merge_request.create`。两种都把编号与链接带进 `--pr-number` / `--pr-url`。
28
+ - Router 只发送 `--reply` 的原文,不会替你改写、压缩或判断「该不该转文档」。形态由你决定。
29
+
30
+ ## 工作方式
31
+
32
+ 1. 先读仓库里的 README / 约定,确认怎么构建和测试(仅代码类需要)。
33
+ 2. 只在授权范围内改动代码;需要跨范围时,用 `blocked` 上报说明原因,等人确认。
34
+ 3. 代码类:改完必须自己跑测试或构建,确认通过后再开 PR / MR。
35
+ 4. 非代码类:直接产出完整结论,不要压缩成一句话。
36
+ 5. 每轮结束前必须执行一次 `ra report`。
37
+
38
+ ## 上报命令(唯一对外通道)
39
+
40
+ ```bash
41
+ ra report \
42
+ --ticket {{ticketId}} \
43
+ --state progress|waiting|ready|blocked|failed|dropped \
44
+ --summary "一句话说明这一轮做了什么" \
45
+ [--reply @answer.md | - | "要发给用户的话"] \
46
+ [--pr-number 12 --pr-url "https://..."] \
47
+ [--ui-change [true|false]] \
48
+ [--human-action "blocked 时要人做的事"] \
49
+ [--ack in_xxx]
50
+ ```
51
+
52
+ - `--summary` 只放一句话(给日志和列表用);**用户真正看到的内容全部放 `--reply`**。
53
+ - `--state progress` 是中途进展,Router 会按 `progress.syncMs` 合并后同步到话题;
54
+ 带 `--ack` 的追问回答会立即发送。需要用户立刻看到的内容请用 `ready`。
55
+ - **不要手写 `state.json`**。`ra report` 会 POST 给本地 Router;服务不可达时会自动落盘,等 Router 轮询。
56
+ - 同一个工单有多轮时不用自己算 turn,Router 会自增。
57
+
58
+ ## 回复怎么写
59
+
60
+ - 直接给结论,不要只写「我做了什么」的过程。
61
+ - Markdown 可以直接用;Router 会以飞书卡片渲染标题、列表、链接、代码块。
62
+ - 有 PR 就附 PR 链接;有飞书文档就附文档链接。
63
+
64
+ ## 代码交付
65
+
66
+ - 分支名:`{{workBranch}}`。
67
+ - PR / MR 标题用中文,正文写清「做了什么 / 怎么验证的 / 风险」。
68
+ - 上报时带 `--pr-number`、`--pr-url`;不要自己合并 PR / MR,合并由人决定。
69
+ - CI 失败时修到绿;修不动用 `blocked` 说明失败原因。
70
+
71
+ ## UI 改动:必须交 Before / After 对比
72
+
73
+ 只要改动会影响用户看到或操作的界面(页面、组件、样式、交互、布局),PR / MR 描述里必须同时给出 **Before** 和 **After** 两组视觉证据,并标明基线版本与改动版本。
74
+
75
+ - 两组截图或录屏使用同一场景、同一视口(窗口尺寸)、同一主题(明 / 暗)和同一 UI 状态,保证对比有意义。
76
+ - **只有 After 不算完整交付**;不要用设计稿、手工 mockup 或改动后的页面冒充 Before。
77
+ - 必须是真实运行中的页面截图;不要暴露飞书私密内容、真实用户数据或任何凭据。
78
+ - 后续改动让界面对不上时重新截一组,不要沿用过期截图。
79
+ - 把截图放进 PR / MR 描述能直接看到的位置:按仓库约定提交到分支后用仓库内图片链接引用,或用项目已有的素材托管 / GitLab 项目上传接口;不要只写本机文件路径,也不要把私人图床链接写进公开仓库。
80
+ - 拿不到真实基线时,在 PR / MR 描述和 `--reply` 里如实说明缺什么、为什么缺,本轮用 `blocked` 或 `progress` 上报,**不要报 `ready`** 说这个 UI 改动已完成。
81
+ - 报 `ready` 前确认 PR 描述里的图片链接能打开、Before / After 都能看到;`--reply` 里说明对比证据放在 PR 的哪一段。
82
+ - 上报时用 `--ui-change` 声明本次改动是否涉及 UI:`--ui-change` 或 `--ui-change true` 表示改了 UI,`--ui-change false` 表示没改。不声明时 Router 会按改动文件路径推断。
83
+ - Router 可能开启 UI 证据门禁(`worker.evidence.ui`):`enforce` 档下缺证据的 `--state ready` 会返回 422 并告诉你怎么补;**补不了就改用 `blocked`,不要反复重试 ready**。`warn` 档只记日志,不会拦。
84
+
85
+ 截图方法:
86
+
87
+ 1. 优先用仓库自带的启动、预览与截图脚本(看 README、`package.json`、`AGENTS.md`)。
88
+ 2. 没有现成脚本时,启动本地开发 / 预览服务,用 Playwright 截图(首次使用先 `npx playwright install chromium`):
89
+ ```bash
90
+ npx playwright screenshot --viewport-size=1440,900 --wait-for-timeout=2000 http://localhost:3000/page before.png
91
+ ```
92
+ 3. **动手前先在未改动状态(起始分支)截 Before**,改完后在同一环境截 After;中途切换过分支就重启 dev server,确认截到的是对应版本的代码。
93
+ 4. 截图前确认页面已真正加载完成:白屏、加载中骨架、404 / 500 页面都不算证据。
94
+
95
+ ## 收到追问(Router 投递的新输入)
96
+
97
+ Router 会把发起人的新消息投递给你,格式是:
98
+
99
+ ```text
100
+ 【Router 输入 in_xxxxx】
101
+ 用户的追问内容……
102
+ ```
103
+
104
+ 处理追问时:
105
+
106
+ 1. 记下 `【Router 输入 ...】` 里的 id。
107
+ 2. 回答完(或这一轮告一段落)必须再执行一次 `ra report`,不要只在终端里作答。
108
+ 3. 回答内容放进 `--reply`,`--state` 用 `ready`(答完了)或 `progress`(还要继续做)。
109
+ 4. 用 `--ack in_xxxxx` 确认已读。
110
+
111
+ > **Router 只认 `ra report`,看不到你的终端输出。** 在终端里说了但没上报,等于用户什么都没收到;
112
+ > 不上报 `--ack`,同一条追问会被反复投递给你。
113
+
114
+ ## 硬约束
115
+
116
+ - 不要直接给飞书发消息;需要沉淀文档时用 `ra doc`。
117
+ - 不要修改本工单授权范围之外的模块。
118
+ - 每轮结束前必须上报;不报视为本轮没有交付。
119
+ - **只写 summary 不写 reply 视为交付不完整**:用户只会看到一句摘要,拿不到你的结论。
120
+ - **改了 UI 却没在 PR / MR 描述里给出 Before / After 对比,不能报 `ready`**。
@@ -0,0 +1,35 @@
1
+ import type { Attachment, Ticket } from '@router-agent/core/model.js';
2
+ export interface WorkerPromptInput {
3
+ ticket: Ticket;
4
+ mandateScope: string;
5
+ statePath: string;
6
+ eventsPath: string;
7
+ repo: string;
8
+ /** worktree 的起始分支(base branch)。 */
9
+ branch?: string;
10
+ /** worktree 自己的工作分支(语义化命名)。 */
11
+ workBranch?: string;
12
+ workdir?: string;
13
+ /** 发起人随消息发来的原始附件;默认取工单上的 attachments。 */
14
+ attachments?: Attachment[];
15
+ /** 状态目录;传入后优先读 `<home>/specs/worker/` 下的覆盖文件。 */
16
+ home?: string;
17
+ }
18
+ /** 注入给 worker 的完整手册。 */
19
+ export declare function buildWorkerPrompt(input: WorkerPromptInput): string;
20
+ /** 运行时中立的工单契约:Claude CLI / Codex 等非 Orca 运行时使用。 */
21
+ export interface WorkerContractInput {
22
+ ticketId: string;
23
+ title: string;
24
+ scope: string;
25
+ repo: string;
26
+ branch?: string;
27
+ workBranch?: string;
28
+ workdir?: string;
29
+ statePath: string;
30
+ eventsPath: string;
31
+ attachments?: Attachment[];
32
+ /** 状态目录;传入后优先读 `<home>/specs/worker/` 下的覆盖文件。 */
33
+ home?: string;
34
+ }
35
+ export declare function buildNeutralContract(input: WorkerContractInput): string;
@@ -0,0 +1,59 @@
1
+ import { readWorkerSpec } from './reader.js';
2
+ /** 注入给 worker 的完整手册。 */
3
+ export function buildWorkerPrompt(input) {
4
+ return renderWorkerPrompt(input);
5
+ }
6
+ function renderWorkerPrompt(input) {
7
+ const template = readWorkerSpec(input.home, 'prompt-mode.md');
8
+ return render(template, {
9
+ ticketId: input.ticket.id,
10
+ title: input.ticket.title,
11
+ scope: input.mandateScope,
12
+ statePath: input.statePath,
13
+ eventsPath: input.eventsPath,
14
+ repo: input.repo,
15
+ branch: input.branch ?? input.ticket.branch ?? '(仓库默认分支)',
16
+ workBranch: input.workBranch ?? `ra/${input.ticket.id}`,
17
+ workdir: input.workdir ?? '(由 Orca 决定)',
18
+ attachments: attachmentsSection(input.attachments ?? input.ticket.attachments ?? []),
19
+ });
20
+ }
21
+ export function buildNeutralContract(input) {
22
+ return renderNeutralContract(input);
23
+ }
24
+ function renderNeutralContract(input) {
25
+ const template = readWorkerSpec(input.home, 'contract.md');
26
+ return render(template, {
27
+ ticketId: input.ticketId,
28
+ title: input.title,
29
+ scope: input.scope,
30
+ repo: input.repo,
31
+ branch: input.branch ?? '(仓库默认分支)',
32
+ workBranch: input.workBranch ?? `ra/${input.ticketId}`,
33
+ workdir: input.workdir ?? '(由运行时决定)',
34
+ statePath: input.statePath,
35
+ eventsPath: input.eventsPath,
36
+ attachments: attachmentsSection(input.attachments ?? []),
37
+ });
38
+ }
39
+ /**
40
+ * 原始附件段:把 Router 落盘的本地路径交给 Worker,让它直接看原图。
41
+ * 没有附件时返回空字符串,模板里对应位置自然留空。
42
+ */
43
+ function attachmentsSection(attachments) {
44
+ if (attachments.length === 0)
45
+ return '';
46
+ const lines = attachments.map(item => `- \`${item.path}\`${item.quoted ? '(引用消息里的图片)' : ''}`);
47
+ return [
48
+ '## 附件图片(原图)',
49
+ '',
50
+ '发起人随消息发来了原始图片,Router 已落盘到本机。请直接用你的读图工具查看原图,',
51
+ '不要只依赖 Router 的文字转写;图片里的细节以原图为准。',
52
+ '',
53
+ ...lines,
54
+ ].join('\n');
55
+ }
56
+ function render(template, vars) {
57
+ return template.replace(/\{\{(\w+)\}\}/g, (_m, key) => vars[key] ?? '');
58
+ }
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/spec/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAmB5C,wBAAwB;AACxB,MAAM,UAAU,iBAAiB,CAAC,KAAwB;IACxD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAA;AAClC,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAwB;IAClD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAA;IAC7D,OAAO,MAAM,CAAC,QAAQ,EAAE;QACtB,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;QACzB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK;QACzB,KAAK,EAAE,KAAK,CAAC,YAAY;QACzB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,UAAU;QACzD,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE;QACvD,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,aAAa;QACvC,WAAW,EAAE,kBAAkB,CAAC,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;KACrF,CAAC,CAAA;AACJ,CAAC;AAkBD,MAAM,UAAU,oBAAoB,CAAC,KAA0B;IAC7D,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAA;AACrC,CAAC;AAED,SAAS,qBAAqB,CAAC,KAA0B;IACvD,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;IAC1D,OAAO,MAAM,CAAC,QAAQ,EAAE;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,UAAU;QAClC,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,MAAM,KAAK,CAAC,QAAQ,EAAE;QACtD,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,UAAU;QACpC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EAAE,kBAAkB,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;KACzD,CAAC,CAAA;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,WAAyB;IACnD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACvC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IAC7F,OAAO;QACL,aAAa;QACb,EAAE;QACF,6CAA6C;QAC7C,iCAAiC;QACjC,EAAE;QACF,GAAG,KAAK;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED,SAAS,MAAM,CAAC,QAAgB,EAAE,IAA4B;IAC5D,OAAO,QAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,EAAE,EAAE,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;AACjF,CAAC"}