openfeel 1.0.9 → 1.1.1

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 (147) hide show
  1. package/README.en.md +11 -11
  2. package/README.md +2 -1
  3. package/README.zh-CN.md +13 -13
  4. package/bin/openfeel.js +2 -2
  5. package/dist/cli/index.d.ts +6 -0
  6. package/dist/cli/index.d.ts.map +1 -1
  7. package/dist/cli/index.js +28 -0
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/commands/archive.d.ts +1 -1
  10. package/dist/commands/flow.d.ts +1 -1
  11. package/dist/commands/flow.d.ts.map +1 -1
  12. package/dist/commands/flow.js +20 -8
  13. package/dist/commands/flow.js.map +1 -1
  14. package/dist/commands/init.d.ts +2 -1
  15. package/dist/commands/init.d.ts.map +1 -1
  16. package/dist/commands/init.js +7 -2
  17. package/dist/commands/init.js.map +1 -1
  18. package/dist/commands/migrate.d.ts +10 -0
  19. package/dist/commands/migrate.d.ts.map +1 -0
  20. package/dist/commands/migrate.js +106 -0
  21. package/dist/commands/migrate.js.map +1 -0
  22. package/dist/commands/model.d.ts +10 -0
  23. package/dist/commands/model.d.ts.map +1 -0
  24. package/dist/commands/model.js +135 -0
  25. package/dist/commands/model.js.map +1 -0
  26. package/dist/commands/setup.d.ts +7 -0
  27. package/dist/commands/setup.d.ts.map +1 -0
  28. package/dist/commands/setup.js +31 -0
  29. package/dist/commands/setup.js.map +1 -0
  30. package/dist/commands/stage.d.ts.map +1 -1
  31. package/dist/commands/stage.js +50 -29
  32. package/dist/commands/stage.js.map +1 -1
  33. package/dist/commands/update.d.ts.map +1 -1
  34. package/dist/commands/update.js +13 -10
  35. package/dist/commands/update.js.map +1 -1
  36. package/dist/commands/view.d.ts +1 -1
  37. package/dist/commands/view.d.ts.map +1 -1
  38. package/dist/commands/view.js +2 -1
  39. package/dist/commands/view.js.map +1 -1
  40. package/dist/core/archive/merge.d.ts.map +1 -1
  41. package/dist/core/archive/merge.js +5 -4
  42. package/dist/core/archive/merge.js.map +1 -1
  43. package/dist/core/artifact-graph/resolver.js +2 -2
  44. package/dist/core/artifact-graph/resolver.js.map +1 -1
  45. package/dist/core/config.d.ts +8 -8
  46. package/dist/core/config.d.ts.map +1 -1
  47. package/dist/core/config.js +22 -17
  48. package/dist/core/config.js.map +1 -1
  49. package/dist/core/flow-manager.d.ts +25 -4
  50. package/dist/core/flow-manager.d.ts.map +1 -1
  51. package/dist/core/flow-manager.js +144 -79
  52. package/dist/core/flow-manager.js.map +1 -1
  53. package/dist/core/fs/atomic-write.d.ts +31 -0
  54. package/dist/core/fs/atomic-write.d.ts.map +1 -0
  55. package/dist/core/fs/atomic-write.js +80 -0
  56. package/dist/core/fs/atomic-write.js.map +1 -0
  57. package/dist/core/fs/file-lock.d.ts +34 -0
  58. package/dist/core/fs/file-lock.d.ts.map +1 -0
  59. package/dist/core/fs/file-lock.js +142 -0
  60. package/dist/core/fs/file-lock.js.map +1 -0
  61. package/dist/core/fs/sequence.d.ts +42 -0
  62. package/dist/core/fs/sequence.d.ts.map +1 -0
  63. package/dist/core/fs/sequence.js +69 -0
  64. package/dist/core/fs/sequence.js.map +1 -0
  65. package/dist/core/global-paths.d.ts +27 -0
  66. package/dist/core/global-paths.d.ts.map +1 -0
  67. package/dist/core/global-paths.js +61 -0
  68. package/dist/core/global-paths.js.map +1 -0
  69. package/dist/core/i18n-data/en.d.ts +3 -0
  70. package/dist/core/i18n-data/en.d.ts.map +1 -1
  71. package/dist/core/i18n-data/en.js +86 -1
  72. package/dist/core/i18n-data/en.js.map +1 -1
  73. package/dist/core/i18n-data/zh-CN.d.ts +3 -0
  74. package/dist/core/i18n-data/zh-CN.d.ts.map +1 -1
  75. package/dist/core/i18n-data/zh-CN.js +87 -1
  76. package/dist/core/i18n-data/zh-CN.js.map +1 -1
  77. package/dist/core/i18n.js +4 -4
  78. package/dist/core/i18n.js.map +1 -1
  79. package/dist/core/init.d.ts +10 -15
  80. package/dist/core/init.d.ts.map +1 -1
  81. package/dist/core/init.js +65 -134
  82. package/dist/core/init.js.map +1 -1
  83. package/dist/core/managed-region.d.ts +54 -0
  84. package/dist/core/managed-region.d.ts.map +1 -0
  85. package/dist/core/managed-region.js +171 -0
  86. package/dist/core/managed-region.js.map +1 -0
  87. package/dist/core/metrics.d.ts.map +1 -1
  88. package/dist/core/metrics.js +6 -3
  89. package/dist/core/metrics.js.map +1 -1
  90. package/dist/core/migrate.d.ts +115 -0
  91. package/dist/core/migrate.d.ts.map +1 -0
  92. package/dist/core/migrate.js +558 -0
  93. package/dist/core/migrate.js.map +1 -0
  94. package/dist/core/model-config.d.ts +62 -0
  95. package/dist/core/model-config.d.ts.map +1 -0
  96. package/dist/core/model-config.js +336 -0
  97. package/dist/core/model-config.js.map +1 -0
  98. package/dist/core/opencode-config.d.ts +17 -0
  99. package/dist/core/opencode-config.d.ts.map +1 -0
  100. package/dist/core/opencode-config.js +135 -0
  101. package/dist/core/opencode-config.js.map +1 -0
  102. package/dist/core/plan/roadmap.d.ts.map +1 -1
  103. package/dist/core/plan/roadmap.js +3 -2
  104. package/dist/core/plan/roadmap.js.map +1 -1
  105. package/dist/core/plan/scheme.d.ts.map +1 -1
  106. package/dist/core/plan/scheme.js +35 -36
  107. package/dist/core/plan/scheme.js.map +1 -1
  108. package/dist/core/plan/stage.d.ts.map +1 -1
  109. package/dist/core/plan/stage.js +4 -3
  110. package/dist/core/plan/stage.js.map +1 -1
  111. package/dist/core/public-logger.d.ts +3 -3
  112. package/dist/core/public-logger.d.ts.map +1 -1
  113. package/dist/core/public-logger.js +36 -40
  114. package/dist/core/public-logger.js.map +1 -1
  115. package/dist/core/setup.d.ts +10 -0
  116. package/dist/core/setup.d.ts.map +1 -0
  117. package/dist/core/setup.js +75 -0
  118. package/dist/core/setup.js.map +1 -0
  119. package/dist/core/template-loader.d.ts +4 -5
  120. package/dist/core/template-loader.d.ts.map +1 -1
  121. package/dist/core/template-loader.js +3974 -3274
  122. package/dist/core/template-loader.js.map +1 -1
  123. package/dist/core/templates.d.ts +2 -2
  124. package/dist/core/templates.d.ts.map +1 -1
  125. package/dist/core/templates.js +2 -2
  126. package/dist/core/templates.js.map +1 -1
  127. package/dist/core/update-infos.d.ts +32 -0
  128. package/dist/core/update-infos.d.ts.map +1 -0
  129. package/dist/core/update-infos.js +153 -0
  130. package/dist/core/update-infos.js.map +1 -0
  131. package/dist/core/update-state.d.ts +18 -0
  132. package/dist/core/update-state.d.ts.map +1 -1
  133. package/dist/core/update-state.js +66 -3
  134. package/dist/core/update-state.js.map +1 -1
  135. package/dist/core/update.d.ts +12 -6
  136. package/dist/core/update.d.ts.map +1 -1
  137. package/dist/core/update.js +400 -550
  138. package/dist/core/update.js.map +1 -1
  139. package/dist/core/view/entry.js +4 -4
  140. package/dist/core/view/entry.js.map +1 -1
  141. package/dist/core/workspace/identity.d.ts.map +1 -1
  142. package/dist/core/workspace/identity.js +13 -10
  143. package/dist/core/workspace/identity.js.map +1 -1
  144. package/dist/core/workspace/knowledge.d.ts.map +1 -1
  145. package/dist/core/workspace/knowledge.js +24 -14
  146. package/dist/core/workspace/knowledge.js.map +1 -1
  147. package/package.json +1 -1
@@ -0,0 +1,62 @@
1
+ /** 三层级 scope */
2
+ export type ModelScope = 'default' | 'global' | 'project';
3
+ /** set 结果 */
4
+ export interface SetModelResult {
5
+ ok: boolean;
6
+ scope: ModelScope;
7
+ agentId: string;
8
+ model: string;
9
+ changedFiles: string[];
10
+ needsBuild?: boolean;
11
+ warning?: string;
12
+ }
13
+ /** get 结果 */
14
+ export interface GetModelResult {
15
+ agentId: string;
16
+ effective?: string;
17
+ byScope: Partial<Record<ModelScope, string | null>>;
18
+ inconsistent?: boolean;
19
+ }
20
+ /** 校验结果 */
21
+ export interface ModelValidation {
22
+ ok: boolean;
23
+ error?: string;
24
+ warning?: string;
25
+ providers?: string[];
26
+ }
27
+ /** 可注入路径(测试隔离用,REV-1506) */
28
+ export interface ModelConfigOptions {
29
+ /** project 层级定位用:项目根路径,默认 process.cwd() */
30
+ projectPath?: string;
31
+ /** default 层级定位用:框架源码根(含 src/core/templates-data 与 src/core/opencode-config.ts),默认由模块位置推导 */
32
+ frameworkRoot?: string;
33
+ }
34
+ /**
35
+ * 判断框架源码是否就位(default scope 预判用,REV-1703)。
36
+ * 路径推导复用 resolveFrameworkRoot(基于 MODULE_DIR),与 core 层落点一致,
37
+ * 避免 CLI 层用 process.cwd() 推导在子目录运行时误报。
38
+ */
39
+ export declare function isFrameworkSourceReady(opts?: ModelConfigOptions): boolean;
40
+ /** 读取 auth.json 顶层 provider key 集合;缺文件/解析失败返回 null(REV-1505) */
41
+ export declare function readAuthProviders(): string[] | null;
42
+ /**
43
+ * 校验模型名格式 + provider(对照 auth.json)。
44
+ * 格式:{provider}/{model-id},两者均非空、不含空白(provider 取自首个 `/` 之前,天然不含 `/`)。
45
+ * provider 硬校验(auth.json key);model-id 软校验(仅格式,提示以 Did you mean 为准)。
46
+ */
47
+ export declare function validateModel(model: string): ModelValidation;
48
+ /**
49
+ * 写指定 scope 的 agent model。
50
+ * default 层:4 有显式 model 的 agent 改 frontmatter 双语 +(vision/reviewer 额外)opencode-config.ts;
51
+ * 5 无显式 model 的 agent 抛错提示用 global/project。
52
+ * global 层:加锁 + 原子写;project 层:仅原子写。
53
+ */
54
+ export declare function setAgentModel(scope: ModelScope, agentIdRaw: string, model: string, opts?: ModelConfigOptions): SetModelResult;
55
+ /**
56
+ * 读 agent model。始终返回完整 byScope(三 scope 显式值)。
57
+ * scope 指定时 effective=该 scope 值;未指定时 effective=default > project > global 首个非空(修正链)。
58
+ */
59
+ export declare function getAgentModel(agentIdRaw: string, scope?: ModelScope, opts?: ModelConfigOptions): GetModelResult;
60
+ /** 列出所有 9 个 agent 的模型(REV-1507:始终返回完整 byScope,scope 仅透传给 get) */
61
+ export declare function listAgentModels(scope?: ModelScope, opts?: ModelConfigOptions): GetModelResult[];
62
+ //# sourceMappingURL=model-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-config.d.ts","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"AAwCA,gBAAgB;AAChB,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1D,aAAa;AACb,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,aAAa;AACb,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,WAAW;AACX,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,4BAA4B;AAC5B,MAAM,WAAW,kBAAkB;IACjC,2CAA2C;IAC3C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,CAAC;CAGxB;AAiCD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAEzE;AAgBD,gEAAgE;AAChE,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,GAAG,IAAI,CAYnD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAgC5D;AAgJD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,kBAAkB,GACxB,cAAc,CA0ChB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,cAAc,CAiB/G;AAED,iEAAiE;AACjE,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,cAAc,EAAE,CAE/F"}
@@ -0,0 +1,336 @@
1
+ /**
2
+ * 模型配置核心模块(stage-40)
3
+ * 提供「工具默认 / 全局 / 当前项目」三层级 agent 模型的读写与校验,
4
+ * 供 CLI(openfeel model)与内部 API(Model not found 报错时自动修复)共用。
5
+ *
6
+ * 三层级落点:
7
+ * - default(工具默认):有显式 model 的 4 个 agent(executor/utility/reviewer/vision)
8
+ * 改 src/core/templates-data/opencode/agents/{zh-CN,en}/*.md frontmatter `model:`(双语);
9
+ * 其中 vision/reviewer 额外改 src/core/opencode-config.ts buildGlobalOpencodeFrameworkObj()
10
+ * 的 agent.<name>.model。无显式 model 的 5 个 agent(feel/planner/schemer/feel-tester/archiver)
11
+ * 报错提示改用 global/project,不新增框架默认条目。
12
+ * - global:~/.config/opencode/opencode.jsonc 的 agent.<name>.model(加锁 + 原子写,只改 model 键)
13
+ * - project:项目根 opencode.jsonc 的 agent.<name>.model(原子写,不加锁)
14
+ *
15
+ * ── 解析优先级(实测勘误,REV-1606)──
16
+ * plan.md §二原写「项目 jsonc > 全局 jsonc > frontmatter > 默认」,op-001 步骤 0 前置实测
17
+ * (隔离 HOME + opencode 1.18.30 `debug config`)推翻该结论。opencode 官方配置源优先级为
18
+ * 「project config < .opencode 目录(agents 等)」,故 agent markdown frontmatter 覆盖 jsonc:
19
+ * 项目 agents/*.md frontmatter > 全局 agents/*.md frontmatter >
20
+ * 项目 opencode.jsonc agent.model > 全局 opencode.jsonc agent.model > opencode 默认
21
+ * 本模块以框架默认源(templates-data frontmatter)代表 default 层(部署后落于全局 agents),
22
+ * 故 effective 解析修正为 `default > project > global`(取首个非空显式值),
23
+ * 且 default 层多源不一致时以 frontmatter 值生效(frontmatter 覆盖 opencode-config.ts 侧)。
24
+ *
25
+ * 本模块为纯函数,不直接 console 输出,返回结构化结果。
26
+ */
27
+ import { existsSync, readFileSync } from 'node:fs';
28
+ import { dirname, join, resolve } from 'node:path';
29
+ import { fileURLToPath } from 'node:url';
30
+ import { atomicWriteFileSync } from './fs/atomic-write.js';
31
+ import { withFileLock, globalLockPath } from './fs/file-lock.js';
32
+ import { getGlobalOpencodeJsoncPath, getAuthJsonPath } from './global-paths.js';
33
+ import { parseJsonc } from './opencode-config.js';
34
+ import { splitFrontmatter, mergeFrontmatter, serializeFrontmatter } from './managed-region.js';
35
+ import { listAgentIds } from './template-loader.js';
36
+ import { normalizeAgentName } from './flow-manager.js';
37
+ import { loadGlobalUpdateState, saveGlobalUpdateState, createGlobalUpdateState, updateFileHash } from './update-state.js';
38
+ // ─── 路径解析 ─────────────────────────────────────────────────────
39
+ /** 模块自身目录(src/core 或 dist/core) */
40
+ const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
41
+ /** default 层级框架源码根:默认由模块位置推导(src/core → 上溯两级到项目根) */
42
+ function resolveFrameworkRoot(opts) {
43
+ if (opts?.frameworkRoot) {
44
+ return resolve(opts.frameworkRoot);
45
+ }
46
+ // model-config 位于 <项目根>/src/core/ 下,框架源码根 = 上溯两级到项目根(含 src/core/templates-data、src/core/opencode-config.ts)
47
+ // 注意:编译到 dist/ 时本目录为 dist/core/,templates-data 不随 tsc 复制,故 default scope 仅在源码仓运行
48
+ // (REV-1601 修订:原 resolve(MODULE_DIR, '..') 只上溯一级到 <项目根>/src,导致拼出 src/src/core/... 双重 src)
49
+ return resolve(MODULE_DIR, '..', '..');
50
+ }
51
+ /** agent 模板目录(zh-CN/en 双语) */
52
+ function agentsTemplatesDir(opts) {
53
+ return join(resolveFrameworkRoot(opts), 'src', 'core', 'templates-data', 'opencode', 'agents');
54
+ }
55
+ /** 指定 agent 的模板文件路径(lang ∈ zh-CN | en) */
56
+ function agentTemplatePath(agentId, lang, opts) {
57
+ return join(agentsTemplatesDir(opts), lang, `${agentId}.md`);
58
+ }
59
+ /** opencode-config.ts 源码路径 */
60
+ function opencodeConfigTsPath(opts) {
61
+ return join(resolveFrameworkRoot(opts), 'src', 'core', 'opencode-config.ts');
62
+ }
63
+ /**
64
+ * 判断框架源码是否就位(default scope 预判用,REV-1703)。
65
+ * 路径推导复用 resolveFrameworkRoot(基于 MODULE_DIR),与 core 层落点一致,
66
+ * 避免 CLI 层用 process.cwd() 推导在子目录运行时误报。
67
+ */
68
+ export function isFrameworkSourceReady(opts) {
69
+ return existsSync(agentsTemplatesDir(opts));
70
+ }
71
+ // ─── agent 名归一化 ───────────────────────────────────────────────
72
+ /** 归一化 agent 名(旧名 → openfeel-* 新名;幂等) */
73
+ function normalizeAgentId(agentId) {
74
+ return normalizeAgentName(agentId);
75
+ }
76
+ /** 判断是否为纯对象 */
77
+ function isPlainObject(v) {
78
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
79
+ }
80
+ // ─── 校验 ─────────────────────────────────────────────────────────
81
+ /** 读取 auth.json 顶层 provider key 集合;缺文件/解析失败返回 null(REV-1505) */
82
+ export function readAuthProviders() {
83
+ const p = getAuthJsonPath();
84
+ if (!existsSync(p)) {
85
+ return null;
86
+ }
87
+ try {
88
+ const obj = JSON.parse(readFileSync(p, 'utf-8'));
89
+ return Array.isArray(obj) ? null : Object.keys(obj);
90
+ }
91
+ catch {
92
+ // auth.json 内容非法 JSON:视为无法核对 provider,降级返回 null
93
+ return null;
94
+ }
95
+ }
96
+ /**
97
+ * 校验模型名格式 + provider(对照 auth.json)。
98
+ * 格式:{provider}/{model-id},两者均非空、不含空白(provider 取自首个 `/` 之前,天然不含 `/`)。
99
+ * provider 硬校验(auth.json key);model-id 软校验(仅格式,提示以 Did you mean 为准)。
100
+ */
101
+ export function validateModel(model) {
102
+ if (typeof model !== 'string' || model.trim() === '') {
103
+ return { ok: false, error: '模型名不能为空,格式应为 {provider}/{model-id}' };
104
+ }
105
+ const m = model.trim();
106
+ const slashIdx = m.indexOf('/');
107
+ if (slashIdx <= 0 || slashIdx === m.length - 1) {
108
+ return { ok: false, error: `模型名格式非法:应为 {provider}/{model-id},实际为 "${m}"` };
109
+ }
110
+ const provider = m.slice(0, slashIdx);
111
+ const modelId = m.slice(slashIdx + 1);
112
+ // provider 取自第一个 "/" 之前,天然不含 "/",故仅需校验空白(REV-1704 移除冗余 includes 判断)
113
+ if (/\s/.test(provider)) {
114
+ return { ok: false, error: `provider 非法(含空白):"${provider}"` };
115
+ }
116
+ if (modelId.trim() === '' || /\s/.test(modelId)) {
117
+ return { ok: false, error: `model-id 非法(为空或含空白):"${modelId}"` };
118
+ }
119
+ // provider 硬校验
120
+ const providers = readAuthProviders();
121
+ if (providers !== null && !providers.includes(provider)) {
122
+ return {
123
+ ok: false,
124
+ error: `provider "${provider}" 不在 auth.json 中`,
125
+ providers,
126
+ };
127
+ }
128
+ const warning = 'model-id 无法离线核对,请以 "Model not found" 报错中的 Did you mean 建议为准';
129
+ if (providers === null) {
130
+ return { ok: true, warning: `${warning}(且未找到 auth.json,无法核对 provider)` };
131
+ }
132
+ return { ok: true, warning };
133
+ }
134
+ // ─── frontmatter 读写(default 层,双语) ─────────────────────────
135
+ /** 读取某语言模板的 frontmatter model;无 frontmatter / 无 model 返回 null */
136
+ function readFrontmatterModel(agentId, lang, opts) {
137
+ const p = agentTemplatePath(agentId, lang, opts);
138
+ if (!existsSync(p)) {
139
+ return null;
140
+ }
141
+ const split = splitFrontmatter(readFileSync(p, 'utf-8'));
142
+ if (!split) {
143
+ return null;
144
+ }
145
+ const v = split.frontmatter.model;
146
+ return typeof v === 'string' && v !== '' ? v : null;
147
+ }
148
+ /** 写某语言模板的 frontmatter model(保留其他字段与正文,REV-1501/控制区标记模式) */
149
+ function writeFrontmatterModel(agentId, lang, model, opts) {
150
+ const p = agentTemplatePath(agentId, lang, opts);
151
+ if (!existsSync(p)) {
152
+ throw new Error(`agent 模板不存在:${p}`);
153
+ }
154
+ const content = readFileSync(p, 'utf-8');
155
+ const split = splitFrontmatter(content);
156
+ if (!split) {
157
+ throw new Error(`agent 模板缺少 frontmatter:${p}`);
158
+ }
159
+ const merged = mergeFrontmatter(split.frontmatter, { model });
160
+ atomicWriteFileSync(p, serializeFrontmatter(merged) + split.body);
161
+ return p;
162
+ }
163
+ // ─── opencode-config.ts 读写(default 层,结构化定位) ────────────
164
+ /**
165
+ * 读 opencode-config.ts 源码中 agent.<name>.model(结构化定位,与写对称)。
166
+ * 用文件文本 + agent 键锚定(非 import 函数),保证写→读往返一致且支持测试隔离(REV-1506)。
167
+ * 无该 agent 条目返回 null。
168
+ */
169
+ function readOpencodeConfigAgentModel(agentId, opts) {
170
+ const p = opencodeConfigTsPath(opts);
171
+ if (!existsSync(p)) {
172
+ return null;
173
+ }
174
+ const text = readFileSync(p, 'utf-8');
175
+ const escaped = agentId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
176
+ const re = new RegExp(`['"]${escaped}['"]\\s*:\\s*\\{\\s*model\\s*:\\s*(['"])([^'"]*?)\\1`, 'g');
177
+ const m = re.exec(text);
178
+ return m ? m[2] : null;
179
+ }
180
+ /**
181
+ * 写 opencode-config.ts 的 agent.<name>.model(REV-1502 结构化定位)。
182
+ * 按 agent 键精确锚定 `'openfeel-vision': { model: '...' }` 条目行替换,避免裸正则误伤。
183
+ * 无该 agent 条目 → 抛错(本阶段 default scope 不新增 opencode-config 条目)。
184
+ */
185
+ function writeOpencodeConfigAgentModel(agentId, model, opts) {
186
+ const p = opencodeConfigTsPath(opts);
187
+ const text = readFileSync(p, 'utf-8');
188
+ const escaped = agentId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
189
+ const re = new RegExp(`(['"]${escaped}['"]\\s*:\\s*\\{\\s*model\\s*:\\s*)(['"])([^'"]*?)(\\2)`, 'g');
190
+ if (!re.test(text)) {
191
+ throw new Error(`opencode-config.ts 无 agent.${agentId}.model 条目,无法更新工具默认模型`);
192
+ }
193
+ re.lastIndex = 0;
194
+ // 用 replacer 函数避免 model 值中的 `$` 被 String.replace 解释为特殊引用
195
+ const updated = text.replace(re, (_match, prefix, q, _old, q2) => `${prefix}${q}${model}${q2}`);
196
+ atomicWriteFileSync(p, updated);
197
+ return p;
198
+ }
199
+ // ─── jsonc 读写(global / project 层) ────────────────────────────
200
+ /** 读 jsonc 的 agent.<name>.model;文件缺失/无条目/解析失败返回 null(REV-1603 修订:补 try/catch) */
201
+ function readJsoncAgentModel(filePath, agentId) {
202
+ if (!existsSync(filePath)) {
203
+ return null;
204
+ }
205
+ let obj;
206
+ try {
207
+ obj = parseJsonc(readFileSync(filePath, 'utf-8'));
208
+ }
209
+ catch {
210
+ // 解析失败(如含 /* */ 块注释)视为无条目,保护读取路径
211
+ return null;
212
+ }
213
+ const agentObj = isPlainObject(obj.agent) ? obj.agent : null;
214
+ if (!agentObj) {
215
+ return null;
216
+ }
217
+ const entry = agentObj[agentId];
218
+ if (!isPlainObject(entry)) {
219
+ return null;
220
+ }
221
+ const v = entry.model;
222
+ return typeof v === 'string' && v !== '' ? v : null;
223
+ }
224
+ /**
225
+ * 写 jsonc 的 agent.<name>.model(REV-1507 只改 model 键,保留同 agent 其他字段与其他 agent)。
226
+ * parse 失败抛错不写盘(保护用户文件,参照 migrate.ts 降级原则)。
227
+ */
228
+ function writeJsoncAgentModel(filePath, agentId, model) {
229
+ const raw = existsSync(filePath) ? readFileSync(filePath, 'utf-8') : '{}\n';
230
+ let obj;
231
+ try {
232
+ obj = parseJsonc(raw);
233
+ }
234
+ catch (err) {
235
+ throw new Error(`opencode.jsonc 解析失败(可能含 /* */ 块注释),已放弃写入保护原文件:${err.message}`);
236
+ }
237
+ const agentObj = isPlainObject(obj.agent) ? obj.agent : {};
238
+ const existing = isPlainObject(agentObj[agentId]) ? agentObj[agentId] : {};
239
+ agentObj[agentId] = { ...existing, model }; // 仅覆盖 model,保留其他字段(REV-1507)
240
+ obj.agent = agentObj;
241
+ atomicWriteFileSync(filePath, JSON.stringify(obj, null, 2) + '\n');
242
+ }
243
+ // ─── default 层读写编排 ───────────────────────────────────────────
244
+ /** 判定 agent 在 default 层是否可写;返回各源是否存在显式 model */
245
+ function defaultScopeSources(agentId, opts) {
246
+ const fmZh = readFrontmatterModel(agentId, 'zh-CN', opts);
247
+ const fmEn = readFrontmatterModel(agentId, 'en', opts);
248
+ const occ = readOpencodeConfigAgentModel(agentId, opts);
249
+ return { frontmatter: fmZh !== null || fmEn !== null, opencodeConfig: occ !== null };
250
+ }
251
+ /**
252
+ * 读取 default 层多源值(REV-1503 + REV-1606 修正链)。
253
+ * frontmatter(agent markdown)加载优先级高于 opencode.jsonc(opencode-config.ts 侧),
254
+ * 故不一致时以 frontmatter 值生效(原方案误以 opencode-config 值生效,实测勘误)。
255
+ */
256
+ function getDefaultScopeValue(agentId, opts) {
257
+ const fmZh = readFrontmatterModel(agentId, 'zh-CN', opts);
258
+ const fmEn = readFrontmatterModel(agentId, 'en', opts);
259
+ const occ = readOpencodeConfigAgentModel(agentId, opts);
260
+ const fm = fmZh ?? fmEn;
261
+ const inconsistent = (occ !== null && fm !== null && occ !== fm) || (fmZh !== fmEn);
262
+ return { value: fm ?? occ, inconsistent };
263
+ }
264
+ // ─── 公开 API ─────────────────────────────────────────────────────
265
+ /**
266
+ * 写指定 scope 的 agent model。
267
+ * default 层:4 有显式 model 的 agent 改 frontmatter 双语 +(vision/reviewer 额外)opencode-config.ts;
268
+ * 5 无显式 model 的 agent 抛错提示用 global/project。
269
+ * global 层:加锁 + 原子写;project 层:仅原子写。
270
+ */
271
+ export function setAgentModel(scope, agentIdRaw, model, opts) {
272
+ const agentId = normalizeAgentId(agentIdRaw);
273
+ const changedFiles = [];
274
+ const validation = validateModel(model);
275
+ if (!validation.ok) {
276
+ throw new Error(`${validation.error}${validation.providers ? `;可用 provider:${validation.providers.join(', ')}` : ''}`);
277
+ }
278
+ if (scope === 'default') {
279
+ const sources = defaultScopeSources(agentId, opts);
280
+ if (!sources.frontmatter && !sources.opencodeConfig) {
281
+ throw new Error(`agent "${agentId}" 无框架默认 model,请改用 --scope global(本机全局)或 --scope project(当前项目)`);
282
+ }
283
+ if (sources.frontmatter) {
284
+ changedFiles.push(writeFrontmatterModel(agentId, 'zh-CN', model, opts));
285
+ changedFiles.push(writeFrontmatterModel(agentId, 'en', model, opts));
286
+ }
287
+ if (sources.opencodeConfig) {
288
+ changedFiles.push(writeOpencodeConfigAgentModel(agentId, model, opts));
289
+ }
290
+ return { ok: true, scope, agentId, model, changedFiles, needsBuild: true, warning: validation.warning };
291
+ }
292
+ if (scope === 'global') {
293
+ const p = getGlobalOpencodeJsoncPath();
294
+ withFileLock(globalLockPath('global-opencode-jsonc'), () => writeJsoncAgentModel(p, agentId, model));
295
+ // REV-1803:与 update.ts 写盘后逻辑一致,同步全局 update_state 的 hash,
296
+ // 避免后续 update 将本次 model 变更误判为用户外部修改
297
+ const globalState = loadGlobalUpdateState() ?? createGlobalUpdateState({});
298
+ updateFileHash(globalState, p, readFileSync(p, 'utf-8'));
299
+ globalState.last_update = new Date().toISOString();
300
+ saveGlobalUpdateState(globalState);
301
+ changedFiles.push(p);
302
+ return { ok: true, scope, agentId, model, changedFiles, warning: validation.warning };
303
+ }
304
+ // project
305
+ const projectPath = resolve(opts?.projectPath ?? process.cwd());
306
+ const p = join(projectPath, 'opencode.jsonc');
307
+ writeJsoncAgentModel(p, agentId, model);
308
+ changedFiles.push(p);
309
+ return { ok: true, scope, agentId, model, changedFiles, warning: validation.warning };
310
+ }
311
+ /**
312
+ * 读 agent model。始终返回完整 byScope(三 scope 显式值)。
313
+ * scope 指定时 effective=该 scope 值;未指定时 effective=default > project > global 首个非空(修正链)。
314
+ */
315
+ export function getAgentModel(agentIdRaw, scope, opts) {
316
+ const agentId = normalizeAgentId(agentIdRaw);
317
+ const projectPath = resolve(opts?.projectPath ?? process.cwd());
318
+ const project = readJsoncAgentModel(join(projectPath, 'opencode.jsonc'), agentId);
319
+ const global = readJsoncAgentModel(getGlobalOpencodeJsoncPath(), agentId);
320
+ const def = getDefaultScopeValue(agentId, opts);
321
+ const byScope = {
322
+ project,
323
+ global,
324
+ default: def.value,
325
+ };
326
+ // 修正链(REV-1606):agent markdown frontmatter(default 层)> 项目 jsonc > 全局 jsonc
327
+ const effective = scope
328
+ ? (byScope[scope] ?? undefined)
329
+ : (def.value ?? project ?? global ?? undefined);
330
+ return { agentId, effective, byScope, inconsistent: def.inconsistent };
331
+ }
332
+ /** 列出所有 9 个 agent 的模型(REV-1507:始终返回完整 byScope,scope 仅透传给 get) */
333
+ export function listAgentModels(scope, opts) {
334
+ return listAgentIds('zh-CN').map((id) => getAgentModel(id, scope, opts));
335
+ }
336
+ //# sourceMappingURL=model-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-config.js","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** 框架级全局 opencode.jsonc 内容对象(N7;全局 AGENTS.md 由约定自动加载承载约束,故不写 instructions) */
2
+ export declare function buildGlobalOpencodeFrameworkObj(): Record<string, unknown>;
3
+ /** 项目 opencode.jsonc 最小覆盖内容(N7:仅 $schema,不写 instructions/skills/default_agent) */
4
+ export declare function buildProjectOpencodeJsoncObj(): Record<string, unknown>;
5
+ /**
6
+ * 解析 JSONC 文本为对象(去 // 行注释后 JSON.parse)。
7
+ * 迁移自 update.ts 的 parseJsonc(op-003 删本地副本改 import 本函数)。
8
+ */
9
+ export declare function parseJsonc(text: string): Record<string, unknown>;
10
+ /**
11
+ * 深度合并两个 opencode 配置对象(overlay=框架 覆盖 base=用户)。
12
+ * 逐字段规则见 op-001 关键设计决策表;用户未知字段 passthrough 保留。
13
+ */
14
+ export declare function deepMergeJsonc(base: Record<string, unknown>, overlay: Record<string, unknown>): Record<string, unknown>;
15
+ /** 合并全局 opencode.jsonc:解析→深度合并→清理废弃 core.md 引用→序列化(保留用户字段,注释不保留) */
16
+ export declare function mergeGlobalOpencodeJsonc(raw: string): string;
17
+ //# sourceMappingURL=opencode-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-config.d.ts","sourceRoot":"","sources":["../../src/core/opencode-config.ts"],"names":[],"mappings":"AAYA,8EAA8E;AAC9E,wBAAgB,+BAA+B,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzE;AAED,kFAAkF;AAClF,wBAAgB,4BAA4B,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEtE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAsBhE;AAoBD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoBzB;AAED,oEAAoE;AACpE,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAe5D"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * 全局 opencode 配置内容与合并逻辑
3
+ * 提供框架级全局 opencode.jsonc 的内容对象、项目最小覆盖内容,
4
+ * 以及 JSONC 解析 / 深度合并 / 序列化,供 init(首次写入)与 update(深度合并)共用。
5
+ */
6
+ import { getGlobalCoreMdPath } from './global-paths.js';
7
+ /** 判断是否为纯对象(排除数组/null) */
8
+ function isPlainObject(v) {
9
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
10
+ }
11
+ /** 框架级全局 opencode.jsonc 内容对象(N7;全局 AGENTS.md 由约定自动加载承载约束,故不写 instructions) */
12
+ export function buildGlobalOpencodeFrameworkObj() {
13
+ return {
14
+ $schema: 'https://opencode.ai/config.json',
15
+ default_agent: 'feel',
16
+ agent: {
17
+ 'openfeel-vision': { model: 'deepseek/deepseek-flash' },
18
+ 'openfeel-reviewer': { model: 'zhipuai/glm-5.3-flash' },
19
+ },
20
+ // N3:experimental.agent_manager_tool 已被移除(op-000 实测 schema 未定义 + 静默丢弃),故不写
21
+ // v1.1.1:instructions 已移除——op-000 实测全局 AGENTS.md 自动加载(YES),约束无需显式 instructions 引用
22
+ };
23
+ }
24
+ /** 项目 opencode.jsonc 最小覆盖内容(N7:仅 $schema,不写 instructions/skills/default_agent) */
25
+ export function buildProjectOpencodeJsoncObj() {
26
+ return { $schema: 'https://opencode.ai/config.json' };
27
+ }
28
+ /**
29
+ * 解析 JSONC 文本为对象(去 // 行注释后 JSON.parse)。
30
+ * 迁移自 update.ts 的 parseJsonc(op-003 删本地副本改 import 本函数)。
31
+ */
32
+ export function parseJsonc(text) {
33
+ const normalized = text.replace(/\r/g, '');
34
+ let result = '';
35
+ let inString = false;
36
+ let inEscape = false;
37
+ let i = 0;
38
+ while (i < normalized.length) {
39
+ const ch = normalized[i];
40
+ const next = normalized[i + 1];
41
+ if (inEscape) {
42
+ result += ch;
43
+ inEscape = false;
44
+ i++;
45
+ continue;
46
+ }
47
+ if (ch === '\\' && inString) {
48
+ result += ch;
49
+ inEscape = true;
50
+ i++;
51
+ continue;
52
+ }
53
+ if (ch === '"') {
54
+ inString = !inString;
55
+ result += ch;
56
+ i++;
57
+ continue;
58
+ }
59
+ if (!inString && ch === '/' && next === '/') {
60
+ i += 2;
61
+ while (i < normalized.length && normalized[i] !== '\n') {
62
+ i++;
63
+ }
64
+ if (i < normalized.length && normalized[i] === '\n') {
65
+ result += '\n';
66
+ i++;
67
+ }
68
+ continue;
69
+ }
70
+ result += ch;
71
+ i++;
72
+ }
73
+ return JSON.parse(result);
74
+ }
75
+ /**
76
+ * 框架 agent 默认值合并(REV-703 修订:粒度为 agent 级)。
77
+ * 仅在用户完全未定义该 agent key 时补入整条 { model };用户定义了该 agent key
78
+ * 即视为完整自定义,框架不补、不覆盖其内部任何字段(如 model)。
79
+ * 与 stage-40 接口兼容:只增补缺失 agent,不重写既有 agent 内字段。
80
+ */
81
+ function mergeAgentDefaults(baseVal, overlayVal) {
82
+ const base = isPlainObject(baseVal) ? baseVal : {};
83
+ const result = { ...base };
84
+ for (const [name, agentOverlay] of Object.entries(overlayVal)) {
85
+ if (!(name in result)) {
86
+ result[name] = agentOverlay;
87
+ }
88
+ }
89
+ return result;
90
+ }
91
+ /**
92
+ * 深度合并两个 opencode 配置对象(overlay=框架 覆盖 base=用户)。
93
+ * 逐字段规则见 op-001 关键设计决策表;用户未知字段 passthrough 保留。
94
+ */
95
+ export function deepMergeJsonc(base, overlay) {
96
+ const result = { ...base };
97
+ for (const [key, overlayVal] of Object.entries(overlay)) {
98
+ if (key === 'instructions' && Array.isArray(overlayVal)) {
99
+ const baseVal = Array.isArray(base[key]) ? base[key] : [];
100
+ result[key] = Array.from(new Set([...overlayVal, ...baseVal]));
101
+ }
102
+ else if (key === 'agent' && isPlainObject(overlayVal)) {
103
+ result[key] = mergeAgentDefaults(base[key], overlayVal);
104
+ }
105
+ else if (key === 'skills') {
106
+ // 框架不写 skills(N6),保留用户已有(result.skills 不动)
107
+ }
108
+ else if (isPlainObject(overlayVal) && isPlainObject(base[key])) {
109
+ result[key] = deepMergeJsonc(base[key], overlayVal);
110
+ }
111
+ else {
112
+ result[key] = overlayVal;
113
+ }
114
+ }
115
+ return result;
116
+ }
117
+ /** 合并全局 opencode.jsonc:解析→深度合并→清理废弃 core.md 引用→序列化(保留用户字段,注释不保留) */
118
+ export function mergeGlobalOpencodeJsonc(raw) {
119
+ const base = parseJsonc(raw);
120
+ const merged = deepMergeJsonc(base, buildGlobalOpencodeFrameworkObj());
121
+ // 移除已废弃的 core.md instructions 引用(v1.1.1:core.md 已并入全局 AGENTS.md)
122
+ const instr = merged.instructions;
123
+ if (Array.isArray(instr)) {
124
+ const stale = getGlobalCoreMdPath();
125
+ const filtered = instr.filter((p) => p !== stale);
126
+ if (filtered.length === 0) {
127
+ delete merged.instructions;
128
+ }
129
+ else {
130
+ merged.instructions = filtered;
131
+ }
132
+ }
133
+ return JSON.stringify(merged, null, 2) + '\n';
134
+ }
135
+ //# sourceMappingURL=opencode-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode-config.js","sourceRoot":"","sources":["../../src/core/opencode-config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"roadmap.d.ts","sourceRoot":"","sources":["../../../src/core/plan/roadmap.ts"],"names":[],"mappings":"AAOA,WAAW;AACX,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAOD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAoCxE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CA0BzE"}
1
+ {"version":3,"file":"roadmap.d.ts","sourceRoot":"","sources":["../../../src/core/plan/roadmap.ts"],"names":[],"mappings":"AAQA,WAAW;AACX,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;CACd;AAOD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAoCxE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CA0BzE"}
@@ -2,8 +2,9 @@
2
2
  * 分期大纲管理
3
3
  * 负责 .openfeel/roadmap/ 下的版本大纲文件创建与读取
4
4
  */
5
- import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
5
+ import { existsSync, mkdirSync, readFileSync, readdirSync } from 'node:fs';
6
6
  import { resolve, join } from 'node:path';
7
+ import { atomicWriteFileSync } from '../fs/atomic-write.js';
7
8
  /** 规范化版本号:去掉用户可能输入的前导 v */
8
9
  function normalizeVersion(version) {
9
10
  return version.replace(/^v/, '');
@@ -41,7 +42,7 @@ export function createRoadmap(projectPath, version) {
41
42
 
42
43
  > 待补充
43
44
  `;
44
- writeFileSync(filePath, content, 'utf-8');
45
+ atomicWriteFileSync(filePath, content);
45
46
  console.log(`已创建分期大纲: v${ver}.md`);
46
47
  }
47
48
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"roadmap.js","sourceRoot":"","sources":["../../../src/core/plan/roadmap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAS1C,2BAA2B;AAC3B,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,OAAe;IAChE,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAEhE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;IAEhD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,GAAG;;;;;;;;;;;;;;;;;CAiB/B,CAAC;IAEA,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,WAAmB,EAAE,OAAgB;IAC/D,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAEhE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,kCAAkC,CAAC;IAC5C,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC9C,CAAC;IAEF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"roadmap.js","sourceRoot":"","sources":["../../../src/core/plan/roadmap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAS5D,2BAA2B;AAC3B,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,OAAe;IAChE,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAEhE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;IAEhD,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,GAAG;;;;;;;;;;;;;;;;;CAiB/B,CAAC;IAEA,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,WAAmB,EAAE,OAAgB;IAC/D,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAEhE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,kCAAkC,CAAC;IAC5C,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC9C,CAAC;IAEF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"scheme.d.ts","sourceRoot":"","sources":["../../../src/core/plan/scheme.ts"],"names":[],"mappings":"AAUA,WAAW;AACX,MAAM,WAAW,MAAM;IACrB,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IACb,YAAY;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB;AAqID;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA8B1F;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+B1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CA6E7E"}
1
+ {"version":3,"file":"scheme.d.ts","sourceRoot":"","sources":["../../../src/core/plan/scheme.ts"],"names":[],"mappings":"AAaA,WAAW;AACX,MAAM,WAAW,MAAM;IACrB,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IACb,YAAY;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;CAClB;AA0HD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAkC1F;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+B1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CA6E7E"}