agents-inc 0.170.1 → 0.170.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/{chunk-BMRUNMPV.js → chunk-2YA4DDRM.js} +35 -35
- package/dist/chunk-2YA4DDRM.js.map +1 -0
- package/dist/{chunk-44TE3RKH.js → chunk-3ED3KHHD.js} +5 -4
- package/dist/chunk-3ED3KHHD.js.map +1 -0
- package/dist/{chunk-3G7X2WKI.js → chunk-5BNX73OU.js} +18 -38
- package/dist/chunk-5BNX73OU.js.map +1 -0
- package/dist/{chunk-7RDMTR64.js → chunk-66AEVERM.js} +785 -256
- package/dist/chunk-66AEVERM.js.map +1 -0
- package/dist/{chunk-PJWGTNOX.js → chunk-7C3PFRBU.js} +144 -186
- package/dist/chunk-7C3PFRBU.js.map +1 -0
- package/dist/{chunk-52HDHJ7I.js → chunk-AUNRHWH4.js} +32 -21
- package/dist/chunk-AUNRHWH4.js.map +1 -0
- package/dist/{chunk-KOLDW6SF.js → chunk-BBDGYJHX.js} +2 -2
- package/dist/chunk-BBDGYJHX.js.map +1 -0
- package/dist/{chunk-SZYQISA2.js → chunk-ELV5WDS3.js} +43 -29
- package/dist/chunk-ELV5WDS3.js.map +1 -0
- package/dist/{chunk-MQ6CGZNJ.js → chunk-GAKVZNTX.js} +1879 -2019
- package/dist/chunk-GAKVZNTX.js.map +1 -0
- package/dist/chunk-GEMW5RQ2.js +1169 -0
- package/dist/chunk-GEMW5RQ2.js.map +1 -0
- package/dist/{chunk-NQW25DCF.js → chunk-GHHJYNAN.js} +1 -7
- package/dist/chunk-GHHJYNAN.js.map +1 -0
- package/dist/{chunk-WTWMGH2C.js → chunk-HACRR422.js} +2 -2
- package/dist/chunk-HACRR422.js.map +1 -0
- package/dist/{chunk-F2BHT5C4.js → chunk-IWY5IR4F.js} +129 -151
- package/dist/chunk-IWY5IR4F.js.map +1 -0
- package/dist/{chunk-JFLVEFFP.js → chunk-KIK5EZYD.js} +1 -1
- package/dist/chunk-KIK5EZYD.js.map +1 -0
- package/dist/{chunk-USVBYQSQ.js → chunk-O4LN3HFI.js} +16 -6
- package/dist/chunk-O4LN3HFI.js.map +1 -0
- package/dist/{chunk-RIPSGNLU.js → chunk-OCAVW6N5.js} +3 -3
- package/dist/chunk-OCAVW6N5.js.map +1 -0
- package/dist/{chunk-4AAOOAIN.js → chunk-P6CYS4JK.js} +2 -2
- package/dist/chunk-P6CYS4JK.js.map +1 -0
- package/dist/chunk-PLFANHRZ.js +35 -0
- package/dist/chunk-PLFANHRZ.js.map +1 -0
- package/dist/{chunk-6ZRH5RHC.js → chunk-PMUZR4XO.js} +4 -4
- package/dist/chunk-PMUZR4XO.js.map +1 -0
- package/dist/{chunk-F5EBEATU.js → chunk-PSUTNOQ2.js} +34 -46
- package/dist/chunk-PSUTNOQ2.js.map +1 -0
- package/dist/chunk-RIK45Q4I.js +103 -0
- package/dist/chunk-RIK45Q4I.js.map +1 -0
- package/dist/{chunk-HED2DAXZ.js → chunk-THO7LO5B.js} +5 -5
- package/dist/chunk-THO7LO5B.js.map +1 -0
- package/dist/{chunk-OYJQUA3D.js → chunk-YGDWHDOY.js} +31 -13
- package/dist/chunk-YGDWHDOY.js.map +1 -0
- package/dist/{chunk-NCWDK6L7.js → chunk-YXKTY5WM.js} +254 -379
- package/dist/chunk-YXKTY5WM.js.map +1 -0
- package/dist/{chunk-NEZ4OAOL.js → chunk-ZEGM3MVR.js} +3 -5
- package/dist/chunk-ZEGM3MVR.js.map +1 -0
- package/dist/commands/build/marketplace.js +46 -46
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +25 -28
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/compile.js +87 -178
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +510 -360
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +451 -357
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +144 -125
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +20 -27
- package/dist/commands/list.js +39 -55
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +6 -11
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/search.js +35 -32
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +17 -77
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +159 -222
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +9 -32
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +2 -2
- package/dist/components/common/removal-plan-confirm.js +2 -2
- package/dist/components/common/scroll-affordance.js +2 -2
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/common/skill-agent-summary.js +4 -4
- package/dist/components/common/spinner.js +2 -4
- package/dist/components/common/summary-panel.js +5 -5
- package/dist/components/common/summary-panel.js.map +1 -1
- package/dist/config-exports.js +7 -3
- package/dist/config-exports.js.map +1 -1
- package/dist/hooks/init.js +18 -19
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/load-agent-defs-6QUUMGHK.js +14 -0
- package/dist/recompile-project-agents-I33KQJFB.js +65 -0
- package/dist/recompile-project-agents-I33KQJFB.js.map +1 -0
- package/dist/{source-loader-C5SQXZXI.js → source-loader-TTJVW2ER.js} +5 -5
- package/dist/src/agents/developer/ai-developer/playbook.md +2 -5
- package/dist/src/agents/developer/api-developer/playbook.md +2 -5
- package/dist/src/agents/developer/cli-developer/playbook.md +2 -5
- package/dist/src/agents/developer/web-developer/playbook.md +2 -5
- package/dist/src/agents/meta/agent-summoner/output.md +2 -2
- package/dist/src/agents/meta/agent-summoner/playbook.md +1 -13
- package/dist/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
- package/dist/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
- package/dist/src/agents/tester/ai-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/ai-tester/playbook.md +2 -0
- package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/api-tester/playbook.md +2 -0
- package/dist/src/agents/tester/cli-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/cli-tester/playbook.md +2 -0
- package/dist/src/agents/tester/web-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/web-tester/playbook.md +2 -0
- package/package.json +9 -8
- package/src/agents/developer/ai-developer/playbook.md +2 -5
- package/src/agents/developer/api-developer/playbook.md +2 -5
- package/src/agents/developer/cli-developer/playbook.md +2 -5
- package/src/agents/developer/web-developer/playbook.md +2 -5
- package/src/agents/meta/agent-summoner/output.md +2 -2
- package/src/agents/meta/agent-summoner/playbook.md +1 -13
- package/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
- package/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
- package/src/agents/tester/ai-tester/critical-requirements.md +1 -2
- package/src/agents/tester/ai-tester/playbook.md +2 -0
- package/src/agents/tester/api-tester/critical-requirements.md +1 -2
- package/src/agents/tester/api-tester/playbook.md +2 -0
- package/src/agents/tester/cli-tester/critical-requirements.md +1 -2
- package/src/agents/tester/cli-tester/playbook.md +2 -0
- package/src/agents/tester/web-tester/critical-requirements.md +1 -2
- package/src/agents/tester/web-tester/playbook.md +2 -0
- package/src/schemas/project-config.schema.json +0 -3
- package/src/schemas/project-source-config.schema.json +0 -6
- package/dist/chunk-3G7X2WKI.js.map +0 -1
- package/dist/chunk-44TE3RKH.js.map +0 -1
- package/dist/chunk-4AAOOAIN.js.map +0 -1
- package/dist/chunk-52HDHJ7I.js.map +0 -1
- package/dist/chunk-6HNXYYVF.js +0 -373
- package/dist/chunk-6HNXYYVF.js.map +0 -1
- package/dist/chunk-6ZRH5RHC.js.map +0 -1
- package/dist/chunk-7RDMTR64.js.map +0 -1
- package/dist/chunk-BMRUNMPV.js.map +0 -1
- package/dist/chunk-CLPUWOSA.js +0 -46
- package/dist/chunk-CLPUWOSA.js.map +0 -1
- package/dist/chunk-F2BHT5C4.js.map +0 -1
- package/dist/chunk-F5EBEATU.js.map +0 -1
- package/dist/chunk-HED2DAXZ.js.map +0 -1
- package/dist/chunk-JFLVEFFP.js.map +0 -1
- package/dist/chunk-KOLDW6SF.js.map +0 -1
- package/dist/chunk-MQ6CGZNJ.js.map +0 -1
- package/dist/chunk-NCWDK6L7.js.map +0 -1
- package/dist/chunk-NEZ4OAOL.js.map +0 -1
- package/dist/chunk-NIHUOWE4.js +0 -106
- package/dist/chunk-NIHUOWE4.js.map +0 -1
- package/dist/chunk-NQW25DCF.js.map +0 -1
- package/dist/chunk-OYJQUA3D.js.map +0 -1
- package/dist/chunk-PJWGTNOX.js.map +0 -1
- package/dist/chunk-RIPSGNLU.js.map +0 -1
- package/dist/chunk-SZYQISA2.js.map +0 -1
- package/dist/chunk-USVBYQSQ.js.map +0 -1
- package/dist/chunk-V3KTSP3Q.js +0 -940
- package/dist/chunk-V3KTSP3Q.js.map +0 -1
- package/dist/chunk-WTWMGH2C.js.map +0 -1
- package/dist/load-agent-defs-YMDWBFDP.js +0 -14
- package/dist/recompile-project-agents-SZ76WNTW.js +0 -18
- package/dist/source-loader-C5SQXZXI.js.map +0 -1
- /package/dist/{load-agent-defs-YMDWBFDP.js.map → load-agent-defs-6QUUMGHK.js.map} +0 -0
- /package/dist/{recompile-project-agents-SZ76WNTW.js.map → source-loader-TTJVW2ER.js.map} +0 -0
|
@@ -2,18 +2,17 @@
|
|
|
2
2
|
import {
|
|
3
3
|
compileAgents,
|
|
4
4
|
withCatalogueSeatedFor
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-IWY5IR4F.js";
|
|
6
6
|
import {
|
|
7
7
|
loadAgentDefs
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-THO7LO5B.js";
|
|
9
9
|
import {
|
|
10
10
|
ConfigLoadError,
|
|
11
11
|
GlobalPairWriteViolation,
|
|
12
|
+
INDENT_STEP,
|
|
12
13
|
assertGateToken,
|
|
14
|
+
brokenUnionLayout,
|
|
13
15
|
buildAndMergeConfig,
|
|
14
|
-
buildConfigTypesBackgroundData,
|
|
15
|
-
deriveCategories,
|
|
16
|
-
deriveDomains,
|
|
17
16
|
detectGlobalInstallation,
|
|
18
17
|
detectInstallation,
|
|
19
18
|
detectProjectInstallation,
|
|
@@ -22,14 +21,14 @@ import {
|
|
|
22
21
|
enableBuffering,
|
|
23
22
|
ensureDir,
|
|
24
23
|
fileExists,
|
|
24
|
+
flatUnion,
|
|
25
25
|
generateBlankGlobalConfigSource,
|
|
26
|
-
generateBlankGlobalConfigTypesSource,
|
|
27
26
|
generateConfigSource,
|
|
28
|
-
generateConfigTypesSource,
|
|
29
27
|
getErrorMessage,
|
|
30
28
|
getInstalledConfigPath,
|
|
31
29
|
getProjectConfigPath,
|
|
32
30
|
isHomeDirectory,
|
|
31
|
+
isRecord,
|
|
33
32
|
loadInstalledConfig,
|
|
34
33
|
loadProjectConfig,
|
|
35
34
|
loadProjectConfigFromDir,
|
|
@@ -37,59 +36,66 @@ import {
|
|
|
37
36
|
mergeConfigs,
|
|
38
37
|
normalizeStackRecord,
|
|
39
38
|
providerInUse,
|
|
39
|
+
quoteText,
|
|
40
40
|
readFile,
|
|
41
|
-
|
|
41
|
+
renderKey,
|
|
42
|
+
renderTypeImportLine,
|
|
43
|
+
renderUnionBody,
|
|
42
44
|
resolveInstallPaths,
|
|
43
45
|
sourceFolderInUse,
|
|
46
|
+
spaces,
|
|
44
47
|
splitConfigByScope,
|
|
45
|
-
typedEntries
|
|
48
|
+
typedEntries,
|
|
49
|
+
typedEntries2,
|
|
50
|
+
typedKeys,
|
|
51
|
+
typedKeys2,
|
|
52
|
+
unionLayout,
|
|
46
53
|
verbose,
|
|
47
54
|
warn,
|
|
48
55
|
withGateToken,
|
|
49
56
|
writeFile
|
|
50
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-GAKVZNTX.js";
|
|
51
58
|
import {
|
|
52
|
-
matrix
|
|
53
|
-
|
|
54
|
-
typedKeys
|
|
55
|
-
} from "./chunk-52HDHJ7I.js";
|
|
59
|
+
matrix
|
|
60
|
+
} from "./chunk-AUNRHWH4.js";
|
|
56
61
|
import {
|
|
57
62
|
CLI_INVOKE_COMMAND,
|
|
63
|
+
CODEX_MODEL_NAMES,
|
|
64
|
+
EFFORT_NAMES,
|
|
58
65
|
GLOBAL_CONFIG_NAME,
|
|
59
66
|
LOCAL_PSEUDO_CATEGORY,
|
|
67
|
+
MODEL_NAMES,
|
|
60
68
|
PROVIDERS,
|
|
61
69
|
STANDARD_FILES,
|
|
70
|
+
activeAgentNames,
|
|
62
71
|
activeProjectAgentNames,
|
|
72
|
+
bytewise,
|
|
73
|
+
globalInstallRoot,
|
|
63
74
|
isActiveAt,
|
|
75
|
+
isExclusiveCategory,
|
|
64
76
|
isGlobalTombstone,
|
|
65
77
|
skillDomain
|
|
66
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-7C3PFRBU.js";
|
|
67
79
|
|
|
68
80
|
// src/cli/lib/operations/source/load-source.ts
|
|
69
81
|
async function loadSource(options) {
|
|
70
82
|
const { caller, sourceFlag, projectDir, captureStartupMessages } = options;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
83
|
+
const load = () => loadSkillsMatrixFromSource({
|
|
84
|
+
...caller !== void 0 && { caller },
|
|
85
|
+
...sourceFlag !== void 0 && { sourceFlag },
|
|
86
|
+
projectDir
|
|
87
|
+
});
|
|
88
|
+
if (!captureStartupMessages) return { sourceResult: await load(), startupMessages: [] };
|
|
89
|
+
return capturingStartupMessages(load);
|
|
90
|
+
}
|
|
91
|
+
async function capturingStartupMessages(load) {
|
|
92
|
+
enableBuffering();
|
|
75
93
|
try {
|
|
76
|
-
sourceResult = await
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
projectDir
|
|
80
|
-
});
|
|
81
|
-
} catch (error) {
|
|
82
|
-
if (captureStartupMessages) {
|
|
83
|
-
disableBuffering();
|
|
84
|
-
}
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
let startupMessages = [];
|
|
88
|
-
if (captureStartupMessages) {
|
|
89
|
-
startupMessages = drainBuffer();
|
|
94
|
+
const sourceResult = await load();
|
|
95
|
+
return { sourceResult, startupMessages: drainBuffer() };
|
|
96
|
+
} finally {
|
|
90
97
|
disableBuffering();
|
|
91
98
|
}
|
|
92
|
-
return { sourceResult, startupMessages };
|
|
93
99
|
}
|
|
94
100
|
function sayCapturedWarnings(messages) {
|
|
95
101
|
for (const { text } of messages) warn(text);
|
|
@@ -123,184 +129,451 @@ async function detectBothInstallations(projectDir) {
|
|
|
123
129
|
return { global, project, hasBoth: !!global && !!project };
|
|
124
130
|
}
|
|
125
131
|
|
|
126
|
-
// src/cli/lib/config-gate/
|
|
127
|
-
import
|
|
128
|
-
import
|
|
132
|
+
// src/cli/lib/config-gate/propagate.ts
|
|
133
|
+
import fs from "fs";
|
|
134
|
+
import { isDeepEqual as isDeepEqual2, unique as unique2 } from "remeda";
|
|
129
135
|
|
|
130
|
-
// src/
|
|
131
|
-
import {
|
|
132
|
-
var
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
stackChanged: false,
|
|
136
|
-
selectedDomainsChanged: false,
|
|
137
|
-
scalarsChanged: [],
|
|
138
|
-
projectsChanged: false
|
|
139
|
-
};
|
|
140
|
-
var EXTRACTED_FIELDS = /* @__PURE__ */ new Set(["skills", "agents", "stack", "selectedDomains"]);
|
|
141
|
-
var REGISTRATION_FIELD = "projects";
|
|
142
|
-
function normalize(config) {
|
|
143
|
-
return JSON.parse(JSON.stringify(config));
|
|
136
|
+
// ../compile/src/config-types-source.ts
|
|
137
|
+
import { groupBy, unique } from "remeda";
|
|
138
|
+
var EMPTY_UNION_TYPE = "never";
|
|
139
|
+
function formatLiteralUnion(members) {
|
|
140
|
+
return flatUnion(members.map(quoteText));
|
|
144
141
|
}
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
var PROJECT_CONFIG_TYPES_BEFORE = `export type InstallMode = 'eject' | 'plugin' | 'mixed'
|
|
143
|
+
|
|
144
|
+
export type SkillConfig = {
|
|
145
|
+
id: SkillId
|
|
146
|
+
scope: 'project' | 'global'
|
|
147
|
+
origin: string
|
|
148
|
+
excluded?: boolean
|
|
147
149
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
|
|
151
|
+
export type AgentScopeConfig = {
|
|
152
|
+
name: AgentName
|
|
153
|
+
scope: 'project' | 'global'
|
|
154
|
+
model?: ${formatLiteralUnion(MODEL_NAMES)}
|
|
155
|
+
codexModel?: ${formatLiteralUnion(CODEX_MODEL_NAMES)}
|
|
156
|
+
effort?: ${formatLiteralUnion(EFFORT_NAMES)}
|
|
157
|
+
excluded?: boolean
|
|
151
158
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
159
|
+
|
|
160
|
+
export type SkillAssignment<S extends SkillId = SkillId> = S | { id: S; preloaded: boolean }
|
|
161
|
+
`;
|
|
162
|
+
var PROJECT_CONFIG_INTERFACE_AFTER = `export interface ProjectConfig {
|
|
163
|
+
/** Project/plugin name (kebab-case) */
|
|
164
|
+
name: string
|
|
165
|
+
|
|
166
|
+
/** Project description */
|
|
167
|
+
description?: string
|
|
168
|
+
|
|
169
|
+
/** Per-agent configuration with scope */
|
|
170
|
+
agents: AgentScopeConfig[]
|
|
171
|
+
|
|
172
|
+
/** Per-skill configuration with scope and provenance */
|
|
173
|
+
skills: SkillConfig[]
|
|
174
|
+
|
|
175
|
+
/** Author handle (e.g., "@vince") */
|
|
176
|
+
author?: string
|
|
177
|
+
|
|
178
|
+
/** Stack configuration: agent -> category -> skill assignment */
|
|
179
|
+
stack?: Partial<Record<ProjectAgentName, StackAgentConfig>>
|
|
180
|
+
|
|
181
|
+
/** The marketplace this install reads skills from, as a path or URL */
|
|
182
|
+
marketplace?: string
|
|
183
|
+
|
|
184
|
+
/** The name that marketplace's manifest gives it, which plugins are registered under */
|
|
185
|
+
marketplaceName?: string
|
|
186
|
+
|
|
187
|
+
/** Selected domains */
|
|
188
|
+
selectedDomains?: Domain[]
|
|
189
|
+
|
|
190
|
+
/** Branding overrides for white-labeling the CLI */
|
|
191
|
+
branding?: { name?: string }
|
|
192
|
+
|
|
193
|
+
/** Custom skills directory override (default: "src/skills") */
|
|
194
|
+
skillsDir?: string
|
|
195
|
+
|
|
196
|
+
/** Custom stacks file path override (default: "config/stacks.ts") */
|
|
197
|
+
stacksFile?: string
|
|
198
|
+
|
|
199
|
+
/** Custom categories file path override (default: "config/skill-categories.ts") */
|
|
200
|
+
categoriesFile?: string
|
|
201
|
+
|
|
202
|
+
/** Custom rules file path override (default: "config/skill-rules.ts") */
|
|
203
|
+
rulesFile?: string
|
|
204
|
+
|
|
205
|
+
/** Tracked project installation paths (global config only) */
|
|
206
|
+
projects?: string[]
|
|
155
207
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return
|
|
208
|
+
`;
|
|
209
|
+
var STACK_AGENT_CONFIG_LOOSE_LINE = "export type StackAgentConfig = Partial<Record<Category, SkillAssignment | SkillAssignment[]>>";
|
|
210
|
+
function assembleConfigTypesSource(parts) {
|
|
211
|
+
const importSection = parts.importBlock ? `${parts.importBlock}
|
|
212
|
+
|
|
213
|
+
` : "";
|
|
214
|
+
return `// AUTO-GENERATED by agents-inc \u2014 DO NOT EDIT
|
|
215
|
+
|
|
216
|
+
${importSection}${renderAlias("SkillId", parts.skillId)}
|
|
217
|
+
|
|
218
|
+
${renderAlias("AgentName", parts.agentName)}
|
|
219
|
+
|
|
220
|
+
${renderAlias("SelectedAgentName", parts.selectedAgentName)}
|
|
221
|
+
|
|
222
|
+
${renderAlias("ProjectAgentName", parts.projectAgentName)}
|
|
223
|
+
|
|
224
|
+
${renderAlias("Domain", parts.domain)}
|
|
225
|
+
|
|
226
|
+
${renderAlias("Category", parts.category)}
|
|
227
|
+
|
|
228
|
+
${PROJECT_CONFIG_TYPES_BEFORE}
|
|
229
|
+
${parts.stackAgentConfig}
|
|
230
|
+
|
|
231
|
+
${PROJECT_CONFIG_INTERFACE_AFTER}`;
|
|
163
232
|
}
|
|
164
|
-
function
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
else otherChanged.push(id);
|
|
233
|
+
function literalUnion(members) {
|
|
234
|
+
return members.length === 0 ? typeReference(EMPTY_UNION_TYPE) : { kind: "plain", members: members.map(quoteText) };
|
|
235
|
+
}
|
|
236
|
+
function typeReference(name) {
|
|
237
|
+
return { kind: "plain", members: [name] };
|
|
238
|
+
}
|
|
239
|
+
function renderAlias(name, rhs) {
|
|
240
|
+
const head = `export type ${name} =`;
|
|
241
|
+
if (rhs.kind === "sectioned") {
|
|
242
|
+
return `${head}
|
|
243
|
+
${renderSectionedUnion(rhs.custom, rhs.marketplace)}`;
|
|
176
244
|
}
|
|
177
|
-
|
|
245
|
+
const layout = unionLayout(rhs.members, {
|
|
246
|
+
headWidth: head.length + " ".length,
|
|
247
|
+
tailWidth: 0,
|
|
248
|
+
bodyIndent: INDENT_STEP
|
|
249
|
+
});
|
|
250
|
+
return layout === "inline" ? `${head} ${flatUnion(rhs.members)}` : `${head}
|
|
251
|
+
${renderUnionBody(rhs.members, layout, INDENT_STEP)}`;
|
|
252
|
+
}
|
|
253
|
+
function renderSectionedUnion(custom, marketplace) {
|
|
254
|
+
if (marketplace.length > 0) {
|
|
255
|
+
return [
|
|
256
|
+
sectionHeading("Custom"),
|
|
257
|
+
renderUnionBody(custom, "stacked", INDENT_STEP),
|
|
258
|
+
sectionHeading("Marketplace"),
|
|
259
|
+
renderUnionBody(marketplace, "stacked", INDENT_STEP)
|
|
260
|
+
].join("\n");
|
|
261
|
+
}
|
|
262
|
+
return [
|
|
263
|
+
sectionHeading("Custom"),
|
|
264
|
+
renderUnionBody(
|
|
265
|
+
custom,
|
|
266
|
+
brokenUnionLayout(custom, INDENT_STEP),
|
|
267
|
+
INDENT_STEP
|
|
268
|
+
)
|
|
269
|
+
].join("\n");
|
|
178
270
|
}
|
|
179
|
-
function
|
|
180
|
-
|
|
181
|
-
|
|
271
|
+
function sectionHeading(text) {
|
|
272
|
+
return `${spaces(INDENT_STEP)}// ${text}`;
|
|
273
|
+
}
|
|
274
|
+
function generateStackAgentConfig(skillsByCategory, catalog) {
|
|
275
|
+
if (skillsByCategory.size === 0) {
|
|
276
|
+
return STACK_AGENT_CONFIG_LOOSE_LINE;
|
|
277
|
+
}
|
|
278
|
+
const properties = [...skillsByCategory.entries()].sort(([a], [b]) => bytewise(a, b)).map(([category, skills]) => renderStackProperty(category, skills, catalog));
|
|
279
|
+
return ["export type StackAgentConfig = {", ...properties, "}"].join("\n");
|
|
280
|
+
}
|
|
281
|
+
function renderStackProperty(category, skills, catalog) {
|
|
282
|
+
const members = [...skills].sort().map(quoteText);
|
|
283
|
+
const tail = `>${isExclusiveCategory(catalog, category) ? "" : "[]"}`;
|
|
284
|
+
const head = `${spaces(INDENT_STEP)}${renderKey(category)}?: SkillAssignment<`;
|
|
285
|
+
const bodyIndent = INDENT_STEP * 2;
|
|
286
|
+
const layout = unionLayout(members, {
|
|
287
|
+
headWidth: head.length,
|
|
288
|
+
tailWidth: tail.length,
|
|
289
|
+
bodyIndent
|
|
290
|
+
});
|
|
291
|
+
if (layout === "inline") return `${head}${flatUnion(members)}${tail}`;
|
|
292
|
+
return [
|
|
293
|
+
head,
|
|
294
|
+
renderUnionBody(members, layout, bodyIndent),
|
|
295
|
+
`${spaces(INDENT_STEP)}${tail}`
|
|
296
|
+
].join("\n");
|
|
297
|
+
}
|
|
298
|
+
function buildSkillsByCategory(skillIds, categories, catalog) {
|
|
299
|
+
const categorySet = new Set(categories);
|
|
300
|
+
const eligible = [...new Set(skillIds)].map((id) => ({ id, category: catalog.skills[id]?.category })).filter(
|
|
301
|
+
(entry) => entry.category !== void 0 && entry.category !== LOCAL_PSEUDO_CATEGORY && // Boundary cast: `string` on the narrow catalogue shape; `has` is the runtime check.
|
|
302
|
+
categorySet.has(entry.category)
|
|
303
|
+
);
|
|
304
|
+
return new Map(
|
|
305
|
+
typedEntries2(groupBy(eligible, (entry) => entry.category)).map(
|
|
306
|
+
([category, entries]) => [category, entries.map((entry) => entry.id)]
|
|
307
|
+
)
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
function isUndeclaredCategory(category, catalog) {
|
|
311
|
+
return catalog.categories[category] === void 0;
|
|
312
|
+
}
|
|
313
|
+
function isCustomSkill(skillId, catalog) {
|
|
314
|
+
const declared = catalog.skills[skillId];
|
|
315
|
+
return declared === void 0 || declared.custom === true;
|
|
316
|
+
}
|
|
317
|
+
function isCustomAgent(agentName, declared, flaggedCustom) {
|
|
318
|
+
return !declared.has(agentName) || flaggedCustom.has(agentName);
|
|
319
|
+
}
|
|
320
|
+
function isCustomDomain(domain, declared) {
|
|
321
|
+
return !declared.has(domain);
|
|
322
|
+
}
|
|
323
|
+
function generateConfigTypesSource(catalog, agentNames, customAgentNames = [], extras, config) {
|
|
324
|
+
const extra = extraMembers(extras);
|
|
325
|
+
const { skillIds, agents, domains, categories } = config ? configMembers(config, extra, catalog) : catalogueMembers(agentNames, extra, catalog);
|
|
326
|
+
const declaredAgents = new Set(agentNames);
|
|
327
|
+
const flaggedCustomAgents = new Set(customAgentNames);
|
|
328
|
+
const declaredDomains = new Set(extractDomains(catalog));
|
|
329
|
+
const skillIdLine = formatMaybeSectionedUnion(
|
|
330
|
+
skillIds,
|
|
331
|
+
(id) => isCustomSkill(id, catalog)
|
|
332
|
+
);
|
|
333
|
+
const agentNameLine = formatMaybeSectionedUnion(
|
|
334
|
+
agents,
|
|
335
|
+
(name) => isCustomAgent(name, declaredAgents, flaggedCustomAgents)
|
|
336
|
+
);
|
|
337
|
+
const domainLine = formatMaybeSectionedUnion(
|
|
338
|
+
domains,
|
|
339
|
+
(domain) => isCustomDomain(domain, declaredDomains)
|
|
340
|
+
);
|
|
341
|
+
const categoryLine = formatMaybeSectionedUnion(
|
|
342
|
+
categories,
|
|
343
|
+
(category) => isUndeclaredCategory(category, catalog)
|
|
344
|
+
);
|
|
345
|
+
const configAgents = config?.agents ?? [];
|
|
346
|
+
const selectedAgentNameLine = narrowedUnion(
|
|
347
|
+
activeAgentNames(configAgents),
|
|
348
|
+
"AgentName"
|
|
349
|
+
);
|
|
350
|
+
const projectAgentNameLine = narrowedUnion(
|
|
351
|
+
activeProjectAgentNames(configAgents),
|
|
352
|
+
"SelectedAgentName"
|
|
353
|
+
);
|
|
354
|
+
const skillsByCategory = buildSkillsByCategory(skillIds, categories, catalog);
|
|
355
|
+
const stackAgentConfigType = generateStackAgentConfig(
|
|
356
|
+
skillsByCategory,
|
|
357
|
+
catalog
|
|
358
|
+
);
|
|
359
|
+
return assembleConfigTypesSource({
|
|
360
|
+
skillId: skillIdLine,
|
|
361
|
+
agentName: agentNameLine,
|
|
362
|
+
selectedAgentName: selectedAgentNameLine,
|
|
363
|
+
projectAgentName: projectAgentNameLine,
|
|
364
|
+
domain: domainLine,
|
|
365
|
+
category: categoryLine,
|
|
366
|
+
stackAgentConfig: stackAgentConfigType
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
function extraMembers(extras) {
|
|
182
370
|
return {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return beforeEntry !== void 0 && !isDeepEqual(beforeEntry, after.get(name));
|
|
188
|
-
})
|
|
371
|
+
skillIds: extras?.extraSkillIds ?? [],
|
|
372
|
+
agents: extras?.extraAgentNames ?? [],
|
|
373
|
+
domains: extras?.extraDomains ?? [],
|
|
374
|
+
categories: extras?.extraCategories ?? []
|
|
189
375
|
};
|
|
190
376
|
}
|
|
191
|
-
function
|
|
192
|
-
const
|
|
193
|
-
const
|
|
194
|
-
|
|
377
|
+
function configMembers(config, extra, catalog) {
|
|
378
|
+
const configSkillIds = config.skills.map((s) => s.id);
|
|
379
|
+
const categories = sortedUnion(
|
|
380
|
+
deriveCategories(configSkillIds, catalog),
|
|
381
|
+
extra.categories
|
|
382
|
+
);
|
|
195
383
|
return {
|
|
196
|
-
|
|
197
|
-
agents:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
384
|
+
skillIds: sortedUnion(configSkillIds, extra.skillIds),
|
|
385
|
+
agents: sortedUnion(
|
|
386
|
+
config.agents.map((a) => a.name),
|
|
387
|
+
extra.agents
|
|
388
|
+
),
|
|
389
|
+
// selectedDomains may carry domains with no skills in this scope.
|
|
390
|
+
domains: sortedUnion(
|
|
391
|
+
deriveDomains(categories, catalog),
|
|
392
|
+
config.selectedDomains ?? [],
|
|
393
|
+
extra.domains
|
|
394
|
+
),
|
|
395
|
+
categories
|
|
202
396
|
};
|
|
203
397
|
}
|
|
204
|
-
function
|
|
205
|
-
|
|
206
|
-
|
|
398
|
+
function catalogueMembers(agentNames, extra, catalog) {
|
|
399
|
+
return {
|
|
400
|
+
skillIds: sortedUnion(typedKeys2(catalog.skills), extra.skillIds),
|
|
401
|
+
agents: sortedUnion(agentNames, extra.agents),
|
|
402
|
+
domains: sortedUnion(extractDomains(catalog), extra.domains),
|
|
403
|
+
categories: sortedUnion(
|
|
404
|
+
typedKeys2(catalog.categories),
|
|
405
|
+
extra.categories
|
|
406
|
+
)
|
|
407
|
+
};
|
|
207
408
|
}
|
|
208
|
-
function
|
|
209
|
-
|
|
210
|
-
if (changes.scalarsChanged.length > 0) return "T2";
|
|
211
|
-
if (changes.projectsChanged) return "T3";
|
|
212
|
-
return "T4";
|
|
409
|
+
function sortedUnion(...lists) {
|
|
410
|
+
return unique(lists.flat()).sort();
|
|
213
411
|
}
|
|
214
|
-
function
|
|
215
|
-
return
|
|
412
|
+
function narrowedUnion(members, fallback) {
|
|
413
|
+
return members.length > 0 ? literalUnion(members) : typeReference(fallback);
|
|
216
414
|
}
|
|
217
|
-
function
|
|
218
|
-
return
|
|
415
|
+
function extractDomains(catalog) {
|
|
416
|
+
return deriveDomains(typedKeys2(catalog.categories), catalog).sort();
|
|
219
417
|
}
|
|
220
|
-
|
|
221
|
-
|
|
418
|
+
var isNonLocalCategory = (category) => Boolean(category) && category !== LOCAL_PSEUDO_CATEGORY;
|
|
419
|
+
function deriveCategories(skillIds, catalog) {
|
|
420
|
+
return unique(
|
|
421
|
+
skillIds.map((id) => catalog.skills[id]?.category).filter(isNonLocalCategory)
|
|
422
|
+
);
|
|
222
423
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
424
|
+
function deriveDomains(categories, catalog) {
|
|
425
|
+
return unique(
|
|
426
|
+
categories.map((cat) => catalog.categories[cat]?.domain).filter((domain) => domain !== void 0)
|
|
427
|
+
);
|
|
227
428
|
}
|
|
228
|
-
|
|
229
|
-
if (
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
429
|
+
function formatMaybeSectionedUnion(members, isCustom) {
|
|
430
|
+
if (members.length === 0) {
|
|
431
|
+
return typeReference(EMPTY_UNION_TYPE);
|
|
432
|
+
}
|
|
433
|
+
const custom = members.filter(isCustom);
|
|
434
|
+
const marketplace = members.filter((m) => !isCustom(m));
|
|
435
|
+
if (custom.length === 0) {
|
|
436
|
+
return literalUnion(members);
|
|
437
|
+
}
|
|
438
|
+
return {
|
|
439
|
+
kind: "sectioned",
|
|
440
|
+
custom: custom.map(quoteText),
|
|
441
|
+
marketplace: marketplace.map(quoteText)
|
|
442
|
+
};
|
|
236
443
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const
|
|
444
|
+
function generateProjectConfigTypesSource(options) {
|
|
445
|
+
const importPath = `${options.globalTypesImportPath}/config-types`;
|
|
446
|
+
const skillIdUnion = formatExtendedUnion(
|
|
447
|
+
"GlobalSkillId",
|
|
448
|
+
options.projectSkillIds
|
|
449
|
+
);
|
|
450
|
+
const agentNameUnion = formatExtendedUnion(
|
|
451
|
+
"GlobalAgentName",
|
|
452
|
+
options.projectAgentNames
|
|
453
|
+
);
|
|
454
|
+
const domainUnion = formatExtendedUnion(
|
|
455
|
+
"GlobalDomain",
|
|
456
|
+
options.projectDomains
|
|
457
|
+
);
|
|
458
|
+
const categoryUnion = formatExtendedUnion(
|
|
459
|
+
"GlobalCategory",
|
|
460
|
+
options.projectCategories ?? []
|
|
461
|
+
);
|
|
462
|
+
const selectedAgentNameUnion = narrowedUnion(
|
|
463
|
+
options.selectedAgentNames ?? [],
|
|
464
|
+
"AgentName"
|
|
465
|
+
);
|
|
466
|
+
const projectAgentNameUnion = narrowedUnion(
|
|
467
|
+
options.projectScopedAgentNames ?? [],
|
|
468
|
+
"SelectedAgentName"
|
|
469
|
+
);
|
|
470
|
+
const importBlock = renderTypeImportLine(
|
|
471
|
+
[
|
|
472
|
+
"SkillId as GlobalSkillId",
|
|
473
|
+
"AgentName as GlobalAgentName",
|
|
474
|
+
"Domain as GlobalDomain",
|
|
475
|
+
"Category as GlobalCategory"
|
|
476
|
+
],
|
|
477
|
+
importPath
|
|
478
|
+
);
|
|
479
|
+
return assembleConfigTypesSource({
|
|
480
|
+
importBlock,
|
|
481
|
+
skillId: skillIdUnion,
|
|
482
|
+
agentName: agentNameUnion,
|
|
483
|
+
selectedAgentName: selectedAgentNameUnion,
|
|
484
|
+
projectAgentName: projectAgentNameUnion,
|
|
485
|
+
domain: domainUnion,
|
|
486
|
+
category: categoryUnion,
|
|
487
|
+
stackAgentConfig: STACK_AGENT_CONFIG_LOOSE_LINE
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
function generateBlankGlobalConfigTypesSource() {
|
|
491
|
+
return assembleConfigTypesSource({
|
|
492
|
+
skillId: typeReference(EMPTY_UNION_TYPE),
|
|
493
|
+
agentName: typeReference(EMPTY_UNION_TYPE),
|
|
494
|
+
selectedAgentName: typeReference(EMPTY_UNION_TYPE),
|
|
495
|
+
projectAgentName: typeReference("SelectedAgentName"),
|
|
496
|
+
domain: typeReference(EMPTY_UNION_TYPE),
|
|
497
|
+
category: typeReference(EMPTY_UNION_TYPE),
|
|
498
|
+
stackAgentConfig: STACK_AGENT_CONFIG_LOOSE_LINE
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
function formatExtendedUnion(globalTypeName, projectMembers) {
|
|
502
|
+
if (projectMembers.length === 0) {
|
|
503
|
+
return typeReference(globalTypeName);
|
|
504
|
+
}
|
|
244
505
|
return {
|
|
245
|
-
|
|
246
|
-
|
|
506
|
+
kind: "plain",
|
|
507
|
+
members: [globalTypeName, ...[...projectMembers].sort().map(quoteText)]
|
|
247
508
|
};
|
|
248
509
|
}
|
|
249
|
-
|
|
250
|
-
|
|
510
|
+
|
|
511
|
+
// src/cli/lib/configuration/config-types-io.ts
|
|
512
|
+
import path from "path";
|
|
513
|
+
async function getGlobalConfigTypesPath(provider) {
|
|
514
|
+
const globalConfigTypesPath = path.join(
|
|
515
|
+
sourceFolderInUse(globalInstallRoot(), provider).dir,
|
|
516
|
+
STANDARD_FILES.CONFIG_TYPES_TS
|
|
517
|
+
);
|
|
518
|
+
if (await fileExists(globalConfigTypesPath)) {
|
|
519
|
+
return globalConfigTypesPath;
|
|
520
|
+
}
|
|
521
|
+
return null;
|
|
251
522
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
return
|
|
523
|
+
function computeGlobalTypesImportPath(projectDir, provider) {
|
|
524
|
+
const projectSourceDir = sourceFolderInUse(projectDir, provider).dir;
|
|
525
|
+
const globalSourceDir = sourceFolderInUse(globalInstallRoot(), provider).dir;
|
|
526
|
+
const relativePath = path.relative(projectSourceDir, globalSourceDir);
|
|
527
|
+
return relativePath.split(path.sep).join("/");
|
|
257
528
|
}
|
|
258
|
-
function
|
|
259
|
-
const
|
|
260
|
-
return
|
|
529
|
+
function buildConfigTypesBackgroundData(matrix2, agents) {
|
|
530
|
+
const agentNames = typedKeys(agents);
|
|
531
|
+
return {
|
|
532
|
+
matrix: matrix2,
|
|
533
|
+
agentNames,
|
|
534
|
+
customAgentNames: agentNames.filter((name) => agents[name]?.custom === true)
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
async function regenerateConfigTypes(projectDir, backgroundData, extras) {
|
|
538
|
+
const provider = providerInUse(projectDir);
|
|
539
|
+
const configTypesPath = path.join(
|
|
540
|
+
sourceFolderInUse(projectDir, provider).dir,
|
|
541
|
+
STANDARD_FILES.CONFIG_TYPES_TS
|
|
542
|
+
);
|
|
543
|
+
if (isHomeDirectory(projectDir)) throw new GlobalPairWriteViolation(configTypesPath);
|
|
544
|
+
const [data, globalConfigTypes, loadedConfig] = await Promise.all([
|
|
545
|
+
backgroundData,
|
|
546
|
+
getGlobalConfigTypesPath(provider),
|
|
547
|
+
loadProjectConfigFromDir(projectDir, provider)
|
|
548
|
+
]);
|
|
549
|
+
const source = globalConfigTypes ? renderTypesExtendingGlobal(projectDir, provider, loadedConfig?.config.agents, extras) : generateConfigTypesSource(
|
|
261
550
|
data.matrix,
|
|
262
551
|
data.agentNames,
|
|
263
552
|
data.customAgentNames,
|
|
264
553
|
extras,
|
|
265
|
-
config
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
async function writeGlobalConfigHalf(config, configPath) {
|
|
269
|
-
return writeIfChanged(configPath, generateConfigSource(config, matrix));
|
|
270
|
-
}
|
|
271
|
-
async function writeGlobalTypesHalf(config, configPath, matrix2, agents, extras) {
|
|
272
|
-
return writeIfChanged(
|
|
273
|
-
typesPathFor(configPath),
|
|
274
|
-
renderStandaloneTypes(config, matrix2, agents, extras)
|
|
275
|
-
);
|
|
276
|
-
}
|
|
277
|
-
async function writeGlobalPair(config, configPath, matrix2, agents) {
|
|
278
|
-
const configWritten = await writeIfChanged(configPath, generateConfigSource(config, matrix2));
|
|
279
|
-
const typesWritten = await writeIfChanged(
|
|
280
|
-
typesPathFor(configPath),
|
|
281
|
-
renderStandaloneTypes(config, matrix2, agents)
|
|
554
|
+
loadedConfig?.config
|
|
282
555
|
);
|
|
283
|
-
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
556
|
+
await writeFile(configTypesPath, source);
|
|
557
|
+
verbose(`Regenerated ${STANDARD_FILES.CONFIG_TYPES_TS}`);
|
|
558
|
+
}
|
|
559
|
+
function renderTypesExtendingGlobal(projectDir, provider, agents, extras) {
|
|
560
|
+
const selectedAgentNames = agents ? activeAgentNames(agents) : void 0;
|
|
561
|
+
const projectScopedAgentNames = agents ? activeProjectAgentNames(agents) : void 0;
|
|
562
|
+
const source = generateProjectConfigTypesSource({
|
|
563
|
+
globalTypesImportPath: computeGlobalTypesImportPath(projectDir, provider),
|
|
564
|
+
projectSkillIds: extras?.extraSkillIds ?? [],
|
|
565
|
+
projectAgentNames: extras?.extraAgentNames ?? [],
|
|
566
|
+
projectDomains: extras?.extraDomains ?? [],
|
|
567
|
+
projectCategories: extras?.extraCategories ?? [],
|
|
568
|
+
...selectedAgentNames?.length ? { selectedAgentNames } : {},
|
|
569
|
+
...projectScopedAgentNames?.length ? { projectScopedAgentNames } : {}
|
|
570
|
+
});
|
|
571
|
+
verbose("Using project config-types.ts that imports from global");
|
|
572
|
+
return source;
|
|
296
573
|
}
|
|
297
574
|
|
|
298
|
-
// src/cli/lib/config-gate/propagate.ts
|
|
299
|
-
import fs from "fs";
|
|
300
|
-
import { isDeepEqual as isDeepEqual3, unique } from "remeda";
|
|
301
|
-
|
|
302
575
|
// ../compile/src/global-config.ts
|
|
303
|
-
import { isDeepEqual
|
|
576
|
+
import { isDeepEqual } from "remeda";
|
|
304
577
|
function additiveMergeStack(existing, incoming) {
|
|
305
578
|
const merged = existing ? structuredClone(existing) : {};
|
|
306
579
|
if (!incoming) return { stack: merged, changed: false };
|
|
@@ -347,15 +620,15 @@ function appendMissingAssignments(existingAssignments, incomingAssignments) {
|
|
|
347
620
|
return changed;
|
|
348
621
|
}
|
|
349
622
|
function mergeGlobalConfigs(existing, incoming) {
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
const newSkills = incomingActiveSkills.filter(
|
|
355
|
-
(s) => !existingSkillIds.has(s.id)
|
|
623
|
+
const newSkills = activeEntriesNotIn(
|
|
624
|
+
incoming.skills,
|
|
625
|
+
existing.skills,
|
|
626
|
+
(s) => s.id
|
|
356
627
|
);
|
|
357
|
-
const newAgents =
|
|
358
|
-
|
|
628
|
+
const newAgents = activeEntriesNotIn(
|
|
629
|
+
incoming.agents,
|
|
630
|
+
existing.agents,
|
|
631
|
+
(a) => a.name
|
|
359
632
|
);
|
|
360
633
|
const mergedSkills = [...existing.skills, ...newSkills];
|
|
361
634
|
const mergedAgents = [...existing.agents, ...newAgents];
|
|
@@ -370,7 +643,7 @@ function mergeGlobalConfigs(existing, incoming) {
|
|
|
370
643
|
])
|
|
371
644
|
];
|
|
372
645
|
const addsEntries = newSkills.length > 0 || newAgents.length > 0;
|
|
373
|
-
const changed = addsEntries || stackChanged || !
|
|
646
|
+
const changed = addsEntries || stackChanged || !isDeepEqual(existing.selectedDomains ?? [], mergedSelectedDomains);
|
|
374
647
|
return {
|
|
375
648
|
config: {
|
|
376
649
|
...existing,
|
|
@@ -383,6 +656,10 @@ function mergeGlobalConfigs(existing, incoming) {
|
|
|
383
656
|
changed
|
|
384
657
|
};
|
|
385
658
|
}
|
|
659
|
+
function activeEntriesNotIn(incoming, existing, keyOf) {
|
|
660
|
+
const held = new Set(existing.map(keyOf));
|
|
661
|
+
return incoming.filter((entry) => !entry.excluded && !held.has(keyOf(entry)));
|
|
662
|
+
}
|
|
386
663
|
function marketplaceIdentityFilledFrom(existing, arriving) {
|
|
387
664
|
const marketplaceName = existing.marketplaceName ?? arriving?.marketplaceName;
|
|
388
665
|
const marketplace = existing.marketplace ?? arriving?.marketplace;
|
|
@@ -437,21 +714,18 @@ function normalizeProjectPath(projectDir) {
|
|
|
437
714
|
async function registerProjectPath(globalConfig, projectDir) {
|
|
438
715
|
const normalizedPath = normalizeProjectPath(projectDir);
|
|
439
716
|
const existing = globalConfig.projects ?? [];
|
|
440
|
-
const
|
|
441
|
-
existing.map(async (p) => ({
|
|
442
|
-
path: p,
|
|
443
|
-
hasConfig: await fileExists(getInstalledConfigPath(p))
|
|
444
|
-
}))
|
|
445
|
-
);
|
|
446
|
-
const valid = staleChecks.filter((c) => c.hasConfig).map((c) => c.path);
|
|
717
|
+
const valid = await projectsStillInstalled(existing);
|
|
447
718
|
if (valid.includes(normalizedPath)) {
|
|
448
719
|
const changed = valid.length !== existing.length;
|
|
449
720
|
return { config: changed ? { ...globalConfig, projects: valid } : globalConfig, changed };
|
|
450
721
|
}
|
|
451
722
|
return { config: { ...globalConfig, projects: [...valid, normalizedPath] }, changed: true };
|
|
452
723
|
}
|
|
453
|
-
function
|
|
454
|
-
|
|
724
|
+
async function projectsStillInstalled(projects) {
|
|
725
|
+
const installed = await Promise.all(
|
|
726
|
+
projects.map((project) => fileExists(getInstalledConfigPath(project)))
|
|
727
|
+
);
|
|
728
|
+
return projects.filter((_, index) => installed[index] === true);
|
|
455
729
|
}
|
|
456
730
|
function globalHasActiveSkill(globalConfig, id) {
|
|
457
731
|
return globalConfig.skills.some((s) => s.id === id && isActiveAt(s, "global"));
|
|
@@ -461,12 +735,12 @@ function globalHasActiveAgent(globalConfig, name) {
|
|
|
461
735
|
}
|
|
462
736
|
function retainProjectOwnedSkills(skills, globalConfig) {
|
|
463
737
|
return skills.filter(
|
|
464
|
-
(entry) =>
|
|
738
|
+
(entry) => entry.scope === "project" || isGlobalTombstone(entry) && globalHasActiveSkill(globalConfig, entry.id)
|
|
465
739
|
);
|
|
466
740
|
}
|
|
467
741
|
function retainProjectOwnedAgents(agents, globalConfig) {
|
|
468
742
|
return agents.filter(
|
|
469
|
-
(entry) =>
|
|
743
|
+
(entry) => entry.scope === "project" || isGlobalTombstone(entry) && globalHasActiveAgent(globalConfig, entry.name)
|
|
470
744
|
);
|
|
471
745
|
}
|
|
472
746
|
function categoryOfSkill(id, matrix2) {
|
|
@@ -474,7 +748,7 @@ function categoryOfSkill(id, matrix2) {
|
|
|
474
748
|
if (category === void 0 || category === LOCAL_PSEUDO_CATEGORY) return void 0;
|
|
475
749
|
return category;
|
|
476
750
|
}
|
|
477
|
-
function
|
|
751
|
+
function isExclusiveCategory2(category, matrix2) {
|
|
478
752
|
return matrix2.categories[category]?.exclusive === true;
|
|
479
753
|
}
|
|
480
754
|
function activeProjectCategories(projectOwnedSkills, matrix2) {
|
|
@@ -488,7 +762,7 @@ function buildProjectCollisionTest(projectOwnedSkills, matrix2) {
|
|
|
488
762
|
);
|
|
489
763
|
const occupiedExclusiveCategories = new Set(
|
|
490
764
|
[...activeProjectCategories(projectOwnedSkills, matrix2)].filter(
|
|
491
|
-
(category) =>
|
|
765
|
+
(category) => isExclusiveCategory2(category, matrix2)
|
|
492
766
|
)
|
|
493
767
|
);
|
|
494
768
|
return (id) => {
|
|
@@ -543,7 +817,7 @@ function computeRemovedGlobalSkillIds(priorProjectSkills, globalConfig) {
|
|
|
543
817
|
);
|
|
544
818
|
return new Set(
|
|
545
819
|
priorProjectSkills.filter(
|
|
546
|
-
(s) => s
|
|
820
|
+
(s) => isActiveAt(s, "global") && !activeGlobalIds.has(s.id) && !projectOwnedIds.has(s.id)
|
|
547
821
|
).map((s) => s.id)
|
|
548
822
|
);
|
|
549
823
|
}
|
|
@@ -585,7 +859,7 @@ function inlinedProjectView(reconciledSplit, effectiveGlobal) {
|
|
|
585
859
|
...reconciledSplit,
|
|
586
860
|
skills: [...effectiveGlobal.skills, ...reconciledSplit.skills],
|
|
587
861
|
agents: [...effectiveGlobal.agents, ...reconciledSplit.agents],
|
|
588
|
-
selectedDomains:
|
|
862
|
+
selectedDomains: unique2([
|
|
589
863
|
...effectiveGlobal.selectedDomains ?? [],
|
|
590
864
|
...reconciledSplit.selectedDomains ?? []
|
|
591
865
|
]),
|
|
@@ -678,6 +952,23 @@ async function propagateToRegisteredProject(projectPath, provider, globalConfig,
|
|
|
678
952
|
return error instanceof ConfigLoadError ? "unreadable" : "failed";
|
|
679
953
|
}
|
|
680
954
|
}
|
|
955
|
+
async function projectsAFanOutReaches(projects, provider) {
|
|
956
|
+
const reached = await Promise.all(
|
|
957
|
+
projects.map(
|
|
958
|
+
async (projectPath) => await wouldBeRewritten(projectPath, provider) ? [projectPath] : []
|
|
959
|
+
)
|
|
960
|
+
);
|
|
961
|
+
return reached.flat();
|
|
962
|
+
}
|
|
963
|
+
async function wouldBeRewritten(projectPath, provider) {
|
|
964
|
+
if (!await holdsAnInstallation(projectPath)) return false;
|
|
965
|
+
if (await whyThisProjectIsNotOurs(projectPath, provider) !== null) return false;
|
|
966
|
+
try {
|
|
967
|
+
return await loadInstalledConfig(projectPath) !== null;
|
|
968
|
+
} catch {
|
|
969
|
+
return false;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
681
972
|
async function holdsAnInstallation(projectPath) {
|
|
682
973
|
const configs = await Promise.all(
|
|
683
974
|
PROVIDERS.map((installed) => fileExists(getProjectConfigPath(projectPath, installed)))
|
|
@@ -713,7 +1004,7 @@ async function resolveEffectiveGlobalConfig(globalSplit, existingGlobalConfig, p
|
|
|
713
1004
|
function matchGlobalToSession(globalSplit, existingGlobalConfig) {
|
|
714
1005
|
if (!existingGlobalConfig) return { config: globalSplit, changed: true };
|
|
715
1006
|
const config = mergeConfigs(globalSplit, existingGlobalConfig, { authoritativeScope: "all" });
|
|
716
|
-
return { config, changed: !
|
|
1007
|
+
return { config, changed: !isDeepEqual2(config, existingGlobalConfig) };
|
|
717
1008
|
}
|
|
718
1009
|
function stackCategories(stack) {
|
|
719
1010
|
return Object.values(stack ?? {}).flatMap((agentStack) => typedKeys(agentStack ?? {}));
|
|
@@ -721,19 +1012,197 @@ function stackCategories(stack) {
|
|
|
721
1012
|
function buildProjectTypesExtras(finalConfig, matrix2) {
|
|
722
1013
|
const activeSkills = finalConfig.skills.filter((s) => !s.excluded);
|
|
723
1014
|
const activeAgents = finalConfig.agents.filter((a) => !a.excluded);
|
|
724
|
-
const extraSkillIds =
|
|
725
|
-
const extraAgentNames =
|
|
726
|
-
const extraCategories =
|
|
1015
|
+
const extraSkillIds = unique2(activeSkills.map((s) => s.id));
|
|
1016
|
+
const extraAgentNames = unique2(activeAgents.map((a) => a.name));
|
|
1017
|
+
const extraCategories = unique2([
|
|
727
1018
|
...deriveCategories(extraSkillIds, matrix2),
|
|
728
1019
|
...stackCategories(finalConfig.stack)
|
|
729
1020
|
]);
|
|
730
|
-
const extraDomains =
|
|
1021
|
+
const extraDomains = unique2([
|
|
731
1022
|
...deriveDomains(extraCategories, matrix2),
|
|
732
1023
|
...finalConfig.selectedDomains ?? []
|
|
733
1024
|
]);
|
|
734
1025
|
return { extraSkillIds, extraAgentNames, extraDomains, extraCategories };
|
|
735
1026
|
}
|
|
736
1027
|
|
|
1028
|
+
// src/cli/lib/config-gate/index.ts
|
|
1029
|
+
import os2 from "os";
|
|
1030
|
+
import path3 from "path";
|
|
1031
|
+
|
|
1032
|
+
// src/cli/lib/config-gate/classify.ts
|
|
1033
|
+
import { isDeepEqual as isDeepEqual3 } from "remeda";
|
|
1034
|
+
var NO_CHANGES = {
|
|
1035
|
+
skills: { added: [], removed: [], sourceChanged: [], otherChanged: [] },
|
|
1036
|
+
agents: { added: [], removed: [], changed: [] },
|
|
1037
|
+
stackChanged: false,
|
|
1038
|
+
selectedDomainsChanged: false,
|
|
1039
|
+
scalarsChanged: [],
|
|
1040
|
+
projectsChanged: false
|
|
1041
|
+
};
|
|
1042
|
+
var EXTRACTED_FIELDS = /* @__PURE__ */ new Set(["skills", "agents", "stack", "selectedDomains"]);
|
|
1043
|
+
var REGISTRATION_FIELD = "projects";
|
|
1044
|
+
var EMPTY_MEANS_ABSENT = /* @__PURE__ */ new Set(["stack", "selectedDomains"]);
|
|
1045
|
+
function isEmptyCollection(value) {
|
|
1046
|
+
return Array.isArray(value) ? value.length === 0 : isRecord(value) && Object.keys(value).length === 0;
|
|
1047
|
+
}
|
|
1048
|
+
function normalize(config) {
|
|
1049
|
+
const record = JSON.parse(JSON.stringify(config));
|
|
1050
|
+
return Object.fromEntries(
|
|
1051
|
+
Object.entries(record).filter(
|
|
1052
|
+
([key, value]) => !(EMPTY_MEANS_ABSENT.has(key) && isEmptyCollection(value))
|
|
1053
|
+
)
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
function skillsById(config) {
|
|
1057
|
+
const skills = config.skills ?? [];
|
|
1058
|
+
return new Map(skills.map((skill) => [skill.id, skill]));
|
|
1059
|
+
}
|
|
1060
|
+
function agentsByName(config) {
|
|
1061
|
+
const agents = config.agents ?? [];
|
|
1062
|
+
return new Map(agents.map((agent) => [agent.name, agent]));
|
|
1063
|
+
}
|
|
1064
|
+
function scalarKeys(prev, next) {
|
|
1065
|
+
const isScalarKey = (key) => !EXTRACTED_FIELDS.has(key) && key !== REGISTRATION_FIELD;
|
|
1066
|
+
const nextKeys = Object.keys(next).filter(isScalarKey);
|
|
1067
|
+
const extraPrevKeys = Object.keys(prev).filter(
|
|
1068
|
+
(key) => isScalarKey(key) && !nextKeys.includes(key)
|
|
1069
|
+
);
|
|
1070
|
+
return [...nextKeys, ...extraPrevKeys];
|
|
1071
|
+
}
|
|
1072
|
+
function diffSkills(prev, next) {
|
|
1073
|
+
const before = skillsById(prev);
|
|
1074
|
+
const after = skillsById(next);
|
|
1075
|
+
const added = [...after.keys()].filter((id) => !before.has(id));
|
|
1076
|
+
const removed = [...before.keys()].filter((id) => !after.has(id));
|
|
1077
|
+
const sourceChanged = [];
|
|
1078
|
+
const otherChanged = [];
|
|
1079
|
+
for (const [id, afterEntry] of after) {
|
|
1080
|
+
const beforeEntry = before.get(id);
|
|
1081
|
+
if (!beforeEntry || isDeepEqual3(beforeEntry, afterEntry)) continue;
|
|
1082
|
+
if (beforeEntry.origin !== afterEntry.origin) sourceChanged.push(id);
|
|
1083
|
+
else otherChanged.push(id);
|
|
1084
|
+
}
|
|
1085
|
+
return { added, removed, sourceChanged, otherChanged };
|
|
1086
|
+
}
|
|
1087
|
+
function diffAgents(prev, next) {
|
|
1088
|
+
const before = agentsByName(prev);
|
|
1089
|
+
const after = agentsByName(next);
|
|
1090
|
+
return {
|
|
1091
|
+
added: [...after.keys()].filter((name) => !before.has(name)),
|
|
1092
|
+
removed: [...before.keys()].filter((name) => !after.has(name)),
|
|
1093
|
+
changed: [...after.keys()].filter((name) => {
|
|
1094
|
+
const beforeEntry = before.get(name);
|
|
1095
|
+
return beforeEntry !== void 0 && !isDeepEqual3(beforeEntry, after.get(name));
|
|
1096
|
+
})
|
|
1097
|
+
};
|
|
1098
|
+
}
|
|
1099
|
+
function classifyGlobalChange(prev, next) {
|
|
1100
|
+
const before = prev ? normalize(prev) : {};
|
|
1101
|
+
const after = normalize(next);
|
|
1102
|
+
const moved = (key) => !isDeepEqual3(before[key], after[key]);
|
|
1103
|
+
return {
|
|
1104
|
+
skills: diffSkills(before, after),
|
|
1105
|
+
agents: diffAgents(before, after),
|
|
1106
|
+
stackChanged: moved("stack"),
|
|
1107
|
+
selectedDomainsChanged: moved("selectedDomains"),
|
|
1108
|
+
scalarsChanged: scalarKeys(before, after).filter(moved),
|
|
1109
|
+
projectsChanged: moved(REGISTRATION_FIELD)
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
function movesTypesOrCompiledAgents(changes) {
|
|
1113
|
+
const { skills, agents } = changes;
|
|
1114
|
+
return skills.added.length > 0 || skills.removed.length > 0 || skills.sourceChanged.length > 0 || skills.otherChanged.length > 0 || agents.added.length > 0 || agents.removed.length > 0 || agents.changed.length > 0 || changes.stackChanged || changes.selectedDomainsChanged;
|
|
1115
|
+
}
|
|
1116
|
+
function consequenceTier(changes) {
|
|
1117
|
+
if (movesTypesOrCompiledAgents(changes)) return "T1";
|
|
1118
|
+
if (changes.scalarsChanged.length > 0) return "T2";
|
|
1119
|
+
if (changes.projectsChanged) return "T3";
|
|
1120
|
+
return "T4";
|
|
1121
|
+
}
|
|
1122
|
+
function tierNeedsDeps(tier) {
|
|
1123
|
+
return tier === "T1" || tier === "T2";
|
|
1124
|
+
}
|
|
1125
|
+
function tierRegeneratesTypes(tier) {
|
|
1126
|
+
return tier === "T1";
|
|
1127
|
+
}
|
|
1128
|
+
function tierPropagates(tier) {
|
|
1129
|
+
return tier === "T1" || tier === "T2";
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
// src/cli/lib/config-gate/deps.ts
|
|
1133
|
+
function isLoaded(deps) {
|
|
1134
|
+
return "matrix" in deps;
|
|
1135
|
+
}
|
|
1136
|
+
async function resolveGateDeps(deps, tier) {
|
|
1137
|
+
if (!tierNeedsDeps(tier)) return null;
|
|
1138
|
+
if (isLoaded(deps)) return deps;
|
|
1139
|
+
const [matrix2, agents] = await Promise.all([
|
|
1140
|
+
deps.loadMatrix(),
|
|
1141
|
+
tierRegeneratesTypes(tier) ? deps.loadAgents() : NO_AGENTS
|
|
1142
|
+
]);
|
|
1143
|
+
return { matrix: matrix2, agents };
|
|
1144
|
+
}
|
|
1145
|
+
var NO_AGENTS = Promise.resolve({});
|
|
1146
|
+
|
|
1147
|
+
// src/cli/lib/config-gate/pair-writer.ts
|
|
1148
|
+
import os from "os";
|
|
1149
|
+
import path2 from "path";
|
|
1150
|
+
function globalPairPaths(provider) {
|
|
1151
|
+
const dir = sourceFolderInUse(os.homedir(), provider).dir;
|
|
1152
|
+
return {
|
|
1153
|
+
configPath: path2.join(dir, STANDARD_FILES.CONFIG_TS),
|
|
1154
|
+
typesPath: path2.join(dir, STANDARD_FILES.CONFIG_TYPES_TS)
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
function typesPathFor(configPath) {
|
|
1158
|
+
return path2.join(path2.dirname(configPath), STANDARD_FILES.CONFIG_TYPES_TS);
|
|
1159
|
+
}
|
|
1160
|
+
async function writeIfChanged(filePath, source) {
|
|
1161
|
+
assertGateToken(filePath);
|
|
1162
|
+
if (await fileExists(filePath) && await readFile(filePath) === source) return false;
|
|
1163
|
+
await writeFile(filePath, source);
|
|
1164
|
+
return true;
|
|
1165
|
+
}
|
|
1166
|
+
function renderStandaloneTypes(config, matrix2, agents, extras) {
|
|
1167
|
+
const data = buildConfigTypesBackgroundData(matrix2, agents);
|
|
1168
|
+
return generateConfigTypesSource(
|
|
1169
|
+
data.matrix,
|
|
1170
|
+
data.agentNames,
|
|
1171
|
+
data.customAgentNames,
|
|
1172
|
+
extras,
|
|
1173
|
+
config
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
async function writeGlobalConfigHalf(config, configPath) {
|
|
1177
|
+
return writeIfChanged(configPath, generateConfigSource(config, matrix));
|
|
1178
|
+
}
|
|
1179
|
+
async function writeGlobalTypesHalf(config, configPath, matrix2, agents, extras) {
|
|
1180
|
+
return writeIfChanged(
|
|
1181
|
+
typesPathFor(configPath),
|
|
1182
|
+
renderStandaloneTypes(config, matrix2, agents, extras)
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
async function writeGlobalPair(config, configPath, matrix2, agents) {
|
|
1186
|
+
const configWritten = await writeIfChanged(configPath, generateConfigSource(config, matrix2));
|
|
1187
|
+
const typesWritten = await writeIfChanged(
|
|
1188
|
+
typesPathFor(configPath),
|
|
1189
|
+
renderStandaloneTypes(config, matrix2, agents)
|
|
1190
|
+
);
|
|
1191
|
+
return configWritten || typesWritten;
|
|
1192
|
+
}
|
|
1193
|
+
async function ensureBlankPair(provider) {
|
|
1194
|
+
const { configPath, typesPath } = globalPairPaths(provider);
|
|
1195
|
+
if (await fileExists(configPath)) {
|
|
1196
|
+
verbose("Global config already exists, skipping blank creation");
|
|
1197
|
+
return false;
|
|
1198
|
+
}
|
|
1199
|
+
await ensureDir(path2.dirname(configPath));
|
|
1200
|
+
await writeIfChanged(configPath, generateBlankGlobalConfigSource());
|
|
1201
|
+
await writeIfChanged(typesPath, generateBlankGlobalConfigTypesSource());
|
|
1202
|
+
verbose(`Created blank global config at ${path2.dirname(configPath)}`);
|
|
1203
|
+
return true;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
737
1206
|
// src/cli/lib/config-gate/recompile.ts
|
|
738
1207
|
var NOTHING_RECOMPILED = {
|
|
739
1208
|
rewrittenCount: 0,
|
|
@@ -741,10 +1210,55 @@ var NOTHING_RECOMPILED = {
|
|
|
741
1210
|
failedCount: 0,
|
|
742
1211
|
warnings: []
|
|
743
1212
|
};
|
|
744
|
-
async function recompilePropagated(projectDirs) {
|
|
1213
|
+
async function recompilePropagated(projectDirs, pairsRewritten) {
|
|
745
1214
|
if (projectDirs.length === 0) return NOTHING_RECOMPILED;
|
|
746
|
-
const { recompilePropagatedProjectAgents
|
|
747
|
-
return
|
|
1215
|
+
const { recompilePropagatedProjectAgents } = await import("./recompile-project-agents-I33KQJFB.js");
|
|
1216
|
+
return recompilePropagatedProjectAgents(projectDirs, pairsRewritten);
|
|
1217
|
+
}
|
|
1218
|
+
function pairRewriteSummary(projectDirs, pairsRewritten) {
|
|
1219
|
+
const rewrittenCount = projectDirs.filter((dir) => pairsRewritten.has(dir)).length;
|
|
1220
|
+
return {
|
|
1221
|
+
rewrittenCount,
|
|
1222
|
+
unchangedCount: projectDirs.length - rewrittenCount,
|
|
1223
|
+
failedCount: 0,
|
|
1224
|
+
warnings: []
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// src/cli/lib/config-gate/pair-snapshot.ts
|
|
1229
|
+
async function readHalf(filePath) {
|
|
1230
|
+
try {
|
|
1231
|
+
return await fileExists(filePath) ? await readFile(filePath) : null;
|
|
1232
|
+
} catch {
|
|
1233
|
+
return Symbol(filePath);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
async function readPair(projectDir, provider) {
|
|
1237
|
+
const configPath = getProjectConfigPath(projectDir, provider);
|
|
1238
|
+
return Promise.all([readHalf(configPath), readHalf(typesPathFor(configPath))]);
|
|
1239
|
+
}
|
|
1240
|
+
async function snapshotProjectPairs(projectDirs, provider) {
|
|
1241
|
+
const pairs = await Promise.all(
|
|
1242
|
+
projectDirs.map(async (dir) => [dir, await readPair(dir, provider)])
|
|
1243
|
+
);
|
|
1244
|
+
return new Map(pairs);
|
|
1245
|
+
}
|
|
1246
|
+
async function pairsRewrittenSince(before, projectDirs, provider) {
|
|
1247
|
+
const judged = await Promise.all(
|
|
1248
|
+
projectDirs.map(async (dir) => ({
|
|
1249
|
+
dir,
|
|
1250
|
+
rewritten: !samePair(snapshotOf(before, dir), await readPair(dir, provider))
|
|
1251
|
+
}))
|
|
1252
|
+
);
|
|
1253
|
+
return new Set(judged.filter(({ rewritten }) => rewritten).map(({ dir }) => dir));
|
|
1254
|
+
}
|
|
1255
|
+
function snapshotOf(before, dir) {
|
|
1256
|
+
const pair = before.get(dir);
|
|
1257
|
+
if (pair === void 0) throw new Error(`No snapshot of ${dir} was taken before the fan-out`);
|
|
1258
|
+
return pair;
|
|
1259
|
+
}
|
|
1260
|
+
function samePair([config, types], [configNow, typesNow]) {
|
|
1261
|
+
return config === configNow && types === typesNow;
|
|
748
1262
|
}
|
|
749
1263
|
|
|
750
1264
|
// src/cli/lib/config-gate/index.ts
|
|
@@ -761,28 +1275,40 @@ function movedGlobalAgentInputs(written) {
|
|
|
761
1275
|
function report(globalWritten, changes, propagated = NOTHING_PROPAGATED, recompile = NOTHING_RECOMPILED) {
|
|
762
1276
|
return { globalWritten, changes, propagated, recompile };
|
|
763
1277
|
}
|
|
1278
|
+
async function fanOut(projects, provider, propagate, recompiles) {
|
|
1279
|
+
const pairsBefore = await snapshotProjectPairs(projects, provider);
|
|
1280
|
+
const propagated = await propagate();
|
|
1281
|
+
const pairsRewritten = await pairsRewrittenSince(pairsBefore, propagated.updated, provider);
|
|
1282
|
+
const recompile = recompiles ? await recompilePropagated(propagated.updated, pairsRewritten) : pairRewriteSummary(propagated.updated, pairsRewritten);
|
|
1283
|
+
return { propagated, recompile };
|
|
1284
|
+
}
|
|
1285
|
+
function sayPropagated(propagated) {
|
|
1286
|
+
if (propagated.updated.length > 0) {
|
|
1287
|
+
verbose(`Propagated global changes to ${propagated.updated.length} project(s)`);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
764
1290
|
async function applyConsequences(globalConfig, changes, deps, provider, currentProjectDir) {
|
|
765
1291
|
const tier = consequenceTier(changes);
|
|
766
|
-
|
|
1292
|
+
const projects = globalConfig.projects ?? [];
|
|
1293
|
+
if (!tierPropagates(tier) || projects.length === 0) {
|
|
767
1294
|
return { propagated: NOTHING_PROPAGATED, recompile: NOTHING_RECOMPILED };
|
|
768
1295
|
}
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
1296
|
+
const regenerateTypes = tierRegeneratesTypes(tier);
|
|
1297
|
+
const reached = await fanOut(
|
|
1298
|
+
projects,
|
|
772
1299
|
provider,
|
|
773
|
-
currentProjectDir,
|
|
774
|
-
|
|
1300
|
+
() => propagateGlobalChangesToProjects(globalConfig, deps.agents, provider, currentProjectDir, {
|
|
1301
|
+
regenerateTypes
|
|
1302
|
+
}),
|
|
1303
|
+
regenerateTypes
|
|
775
1304
|
);
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
}
|
|
779
|
-
const recompile = tierRegeneratesTypes(tier) ? await recompilePropagated(propagated.updated) : NOTHING_RECOMPILED;
|
|
780
|
-
return { propagated, recompile };
|
|
1305
|
+
sayPropagated(reached.propagated);
|
|
1306
|
+
return reached;
|
|
781
1307
|
}
|
|
782
1308
|
function lazyGateDeps(projectDir) {
|
|
783
1309
|
return {
|
|
784
1310
|
loadMatrix: async () => {
|
|
785
|
-
const { loadSkillsMatrixFromSource: loadSkillsMatrixFromSource2 } = await import("./source-loader-
|
|
1311
|
+
const { loadSkillsMatrixFromSource: loadSkillsMatrixFromSource2 } = await import("./source-loader-TTJVW2ER.js");
|
|
786
1312
|
const { matrix: matrix2 } = await loadSkillsMatrixFromSource2({
|
|
787
1313
|
projectDir,
|
|
788
1314
|
skipExtraSources: true,
|
|
@@ -791,27 +1317,33 @@ function lazyGateDeps(projectDir) {
|
|
|
791
1317
|
return matrix2;
|
|
792
1318
|
},
|
|
793
1319
|
loadAgents: async () => {
|
|
794
|
-
const { loadAgentDefs: loadAgentDefs2 } = await import("./load-agent-defs-
|
|
1320
|
+
const { loadAgentDefs: loadAgentDefs2 } = await import("./load-agent-defs-6QUUMGHK.js");
|
|
795
1321
|
return (await loadAgentDefs2()).agents;
|
|
796
1322
|
}
|
|
797
1323
|
};
|
|
798
1324
|
}
|
|
799
1325
|
async function writeConfigByScope(args) {
|
|
800
1326
|
return withGateToken(async () => {
|
|
801
|
-
const {
|
|
1327
|
+
const { matrix: matrix2, agents, projectDir } = args;
|
|
802
1328
|
const homeDir = os2.homedir();
|
|
803
1329
|
const deps = { matrix: matrix2, agents };
|
|
804
|
-
|
|
805
|
-
return writeFromProjectContext(args, homeDir, deps);
|
|
806
|
-
}
|
|
807
|
-
const provider = providerInUse(homeDir);
|
|
808
|
-
const priorGlobal = await loadProjectConfigFromDir(homeDir, provider);
|
|
809
|
-
const changes = classifyGlobalChange(priorGlobal?.config, finalConfig);
|
|
810
|
-
const globalWritten = await writeGlobalPair(finalConfig, projectConfigPath, matrix2, agents);
|
|
811
|
-
const { propagated, recompile } = await applyConsequences(finalConfig, changes, deps, provider);
|
|
812
|
-
return report(globalWritten, changes, propagated, recompile);
|
|
1330
|
+
return isHomeDirectory(projectDir) ? writeFromHome(args, homeDir, deps) : writeFromProjectContext(args, homeDir, deps);
|
|
813
1331
|
});
|
|
814
1332
|
}
|
|
1333
|
+
async function writeFromHome(args, homeDir, deps) {
|
|
1334
|
+
const { finalConfig, projectConfigPath } = args;
|
|
1335
|
+
const provider = providerInUse(homeDir);
|
|
1336
|
+
const priorGlobal = await loadProjectConfigFromDir(homeDir, provider);
|
|
1337
|
+
const changes = classifyGlobalChange(priorGlobal?.config, finalConfig);
|
|
1338
|
+
const globalWritten = await writeGlobalPair(
|
|
1339
|
+
finalConfig,
|
|
1340
|
+
projectConfigPath,
|
|
1341
|
+
deps.matrix,
|
|
1342
|
+
deps.agents
|
|
1343
|
+
);
|
|
1344
|
+
const { propagated, recompile } = await applyConsequences(finalConfig, changes, deps, provider);
|
|
1345
|
+
return report(globalWritten, changes, propagated, recompile);
|
|
1346
|
+
}
|
|
815
1347
|
async function writeFromProjectContext(args, homeDir, deps) {
|
|
816
1348
|
const { finalConfig, projectDir } = args;
|
|
817
1349
|
const { global: globalConfig, project: projectSplitConfig } = splitConfigByScope(finalConfig);
|
|
@@ -853,7 +1385,7 @@ async function writeGlobalPairWhenChanged(effective, globalConfigPath, deps) {
|
|
|
853
1385
|
verbose("Global config unchanged, skipping write");
|
|
854
1386
|
return false;
|
|
855
1387
|
}
|
|
856
|
-
await ensureDir(
|
|
1388
|
+
await ensureDir(path3.dirname(globalConfigPath));
|
|
857
1389
|
const written = await writeGlobalPair(
|
|
858
1390
|
effective.config,
|
|
859
1391
|
globalConfigPath,
|
|
@@ -870,7 +1402,7 @@ async function writeProjectPairWhenOwed(project, provider, reconciledProjectConf
|
|
|
870
1402
|
);
|
|
871
1403
|
return;
|
|
872
1404
|
}
|
|
873
|
-
await ensureDir(
|
|
1405
|
+
await ensureDir(path3.dirname(project.projectConfigPath));
|
|
874
1406
|
await writeProjectConfigPair(
|
|
875
1407
|
project.projectDir,
|
|
876
1408
|
provider,
|
|
@@ -909,16 +1441,14 @@ async function reconcileTypesFromDisk(projectDir, config, deps, options) {
|
|
|
909
1441
|
const globalWritten = await writeScopeConfigTypes(projectDir, config, deps, options?.extras);
|
|
910
1442
|
if (!isHomeDirectory(projectDir)) return report(false, changes);
|
|
911
1443
|
if (!config.projects?.length) return report(globalWritten, changes);
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
options?.currentProjectDir
|
|
1444
|
+
const provider = providerInUse(projectDir);
|
|
1445
|
+
const { propagated, recompile } = await fanOut(
|
|
1446
|
+
config.projects,
|
|
1447
|
+
provider,
|
|
1448
|
+
() => propagateGlobalChangesToProjects(config, deps.agents, provider, options?.currentProjectDir),
|
|
1449
|
+
true
|
|
917
1450
|
);
|
|
918
|
-
|
|
919
|
-
verbose(`Propagated global changes to ${propagated.updated.length} project(s)`);
|
|
920
|
-
}
|
|
921
|
-
const recompile = await recompilePropagated(propagated.updated);
|
|
1451
|
+
sayPropagated(propagated);
|
|
922
1452
|
return report(globalWritten, changes, propagated, recompile);
|
|
923
1453
|
});
|
|
924
1454
|
}
|
|
@@ -981,12 +1511,12 @@ async function propagateGlobalRemoval(preRemovalGlobalConfig, deps, provider) {
|
|
|
981
1511
|
skills: [],
|
|
982
1512
|
agents: []
|
|
983
1513
|
});
|
|
984
|
-
const propagated = await
|
|
985
|
-
preRemovalGlobalConfig,
|
|
986
|
-
|
|
987
|
-
provider
|
|
1514
|
+
const { propagated, recompile } = await fanOut(
|
|
1515
|
+
preRemovalGlobalConfig.projects ?? [],
|
|
1516
|
+
provider,
|
|
1517
|
+
() => pruneGlobalEntriesFromRegisteredProjects(preRemovalGlobalConfig, deps.agents, provider),
|
|
1518
|
+
true
|
|
988
1519
|
);
|
|
989
|
-
const recompile = await recompilePropagated(propagated.updated);
|
|
990
1520
|
return report(false, changes, propagated, recompile);
|
|
991
1521
|
});
|
|
992
1522
|
}
|
|
@@ -1002,7 +1532,7 @@ async function writeProjectPartial(projectDir, partial, options = {}) {
|
|
|
1002
1532
|
throw new GlobalPairWriteViolation(getInstalledConfigPath(projectDir));
|
|
1003
1533
|
}
|
|
1004
1534
|
const configPath = getInstalledConfigPath(projectDir);
|
|
1005
|
-
await ensureDir(
|
|
1535
|
+
await ensureDir(path3.dirname(configPath));
|
|
1006
1536
|
await writeFile(
|
|
1007
1537
|
configPath,
|
|
1008
1538
|
generateConfigSource(
|
|
@@ -1013,11 +1543,11 @@ async function writeProjectPartial(projectDir, partial, options = {}) {
|
|
|
1013
1543
|
}
|
|
1014
1544
|
|
|
1015
1545
|
// src/cli/lib/operations/project/write-project-config.ts
|
|
1016
|
-
import
|
|
1546
|
+
import path4 from "path";
|
|
1017
1547
|
async function writeProjectConfig(options) {
|
|
1018
1548
|
const { selection, sourceResult, projectDir, sourceFlag } = options;
|
|
1019
1549
|
const projectPaths = resolveInstallPaths(projectDir, "project");
|
|
1020
|
-
await ensureDir(
|
|
1550
|
+
await ensureDir(path4.dirname(projectPaths.configPath));
|
|
1021
1551
|
const { agents } = options.agentDefs ?? await loadAgentDefs();
|
|
1022
1552
|
const mergeResult = await buildAndMergeConfig(
|
|
1023
1553
|
selection,
|
|
@@ -1038,9 +1568,7 @@ async function writeProjectConfig(options) {
|
|
|
1038
1568
|
projectDir,
|
|
1039
1569
|
projectConfigPath: projectPaths.configPath,
|
|
1040
1570
|
projectInstallationExists: isProjectContext,
|
|
1041
|
-
//
|
|
1042
|
-
// config a project write commits here, and the two files disagree the moment it does not
|
|
1043
|
-
// reach both: a row preserved for a skill whose directory the removal diff deleted.
|
|
1571
|
+
// Must match the merger's, or the global config and the project rows disagree.
|
|
1044
1572
|
...options.authoritativeScope !== void 0 && {
|
|
1045
1573
|
authoritativeScope: options.authoritativeScope
|
|
1046
1574
|
}
|
|
@@ -1102,6 +1630,7 @@ export {
|
|
|
1102
1630
|
sayCapturedWarnings,
|
|
1103
1631
|
detectProject,
|
|
1104
1632
|
detectBothInstallations,
|
|
1633
|
+
projectsAFanOutReaches,
|
|
1105
1634
|
movedGlobalAgentInputs,
|
|
1106
1635
|
lazyGateDeps,
|
|
1107
1636
|
reconcileTypesFromDisk,
|
|
@@ -1113,4 +1642,4 @@ export {
|
|
|
1113
1642
|
compileAgentsAllScopes,
|
|
1114
1643
|
compileProjectScope
|
|
1115
1644
|
};
|
|
1116
|
-
//# sourceMappingURL=chunk-
|
|
1645
|
+
//# sourceMappingURL=chunk-66AEVERM.js.map
|