@caupulican/pi-adaptative 0.80.84 → 0.80.86
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 +29 -0
- package/dist/core/agent-session.d.ts +20 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +113 -6
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/cost-guard.d.ts +1 -1
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js +2 -2
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/profile-registry.d.ts +2 -1
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +32 -2
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -1
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +2 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +33 -3
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/modes/interactive/components/profile-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/profile-selector.js +2 -0
- package/dist/modes/interactive/components/profile-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +3 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +3 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* automatically reduce reasoning effort before a runaway billing spike — a proactive ceiling, not a
|
|
7
7
|
* reactive cleanup. Pure functions: no I/O, fully testable.
|
|
8
8
|
*/
|
|
9
|
-
/** Per-token USD prices
|
|
9
|
+
/** Per-million-token USD prices, as carried on `Model.cost`. */
|
|
10
10
|
export interface ModelTokenCost {
|
|
11
11
|
input: number;
|
|
12
12
|
output: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost-guard.d.ts","sourceRoot":"","sources":["../../src/core/cost-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,
|
|
1
|
+
{"version":3,"file":"cost-guard.d.ts","sourceRoot":"","sources":["../../src/core/cost-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,cAAc,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,MAAM,CAQT;AAED,qEAAqE;AACrE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,WAAW,CAAC;AAEnD,MAAM,WAAW,iBAAiB;IACjC,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,iGAAiG;IACjG,MAAM,EAAE,eAAe,CAAC;CACxB;AAED,eAAO,MAAM,2BAA2B,EAAE,iBAGzC,CAAC;AAEF,MAAM,WAAW,iBAAiB;IACjC,iFAAiF;IACjF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;CACxB;AAED,0GAA0G;AAC1G,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,iBAAiB,CAQhG;AAED,qGAAqG;AACrG,QAAA,MAAM,gBAAgB,+DAAgE,CAAC;AACvF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,MAAM,CAI3E","sourcesContent":["/**\n * Proactive per-turn token cost guard (Hermes-parity superiority item #34).\n *\n * Hermes (and pi today) only react to context growth by compressing AFTER it's expensive. This estimates\n * the dollar cost of the NEXT LLM call BEFORE it is submitted, so the agent can warn the user or\n * automatically reduce reasoning effort before a runaway billing spike — a proactive ceiling, not a\n * reactive cleanup. Pure functions: no I/O, fully testable.\n */\n\n/** Per-million-token USD prices, as carried on `Model.cost`. */\nexport interface ModelTokenCost {\n\tinput: number;\n\toutput: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n}\n\n/**\n * Estimate the USD cost of one turn: the whole current context is billed as input, plus up to\n * `maxOutputTokens` of output. `cachedInputTokens` (prefix-cache hits) are billed at the cheaper\n * cache-read rate instead of the full input rate. This is an UPPER bound on the turn (it assumes the\n * model emits its full output budget), which is what a spending ceiling should bound against.\n */\nexport function estimateTurnCostUsd(args: {\n\tinputTokens: number;\n\tmaxOutputTokens: number;\n\tcost: ModelTokenCost;\n\tcachedInputTokens?: number;\n}): number {\n\tconst { inputTokens, maxOutputTokens, cost } = args;\n\tconst cached = Math.max(0, Math.min(args.cachedInputTokens ?? 0, inputTokens));\n\tconst freshInput = inputTokens - cached;\n\tconst cacheReadRate = cost.cacheRead ?? cost.input;\n\tconst inputUsd = (freshInput * cost.input + cached * cacheReadRate) / 1_000_000;\n\tconst outputUsd = (Math.max(0, maxOutputTokens) * cost.output) / 1_000_000;\n\treturn inputUsd + outputUsd;\n}\n\n/** What to do when a turn's projected cost exceeds the threshold. */\nexport type CostGuardAction = \"warn\" | \"downgrade\";\n\nexport interface CostGuardSettings {\n\t/** Per-turn USD ceiling. `0` (default) disables the guard entirely. */\n\tmaxTurnUsd: number;\n\t/** Over the ceiling: `warn` (surface a notice) or `downgrade` (also reduce reasoning effort). */\n\taction: CostGuardAction;\n}\n\nexport const DEFAULT_COST_GUARD_SETTINGS: CostGuardSettings = {\n\tmaxTurnUsd: 0,\n\taction: \"warn\",\n};\n\nexport interface CostGuardDecision {\n\t/** True when the guard is enabled AND the projected cost exceeds the ceiling. */\n\tover: boolean;\n\testUsd: number;\n\tthresholdUsd: number;\n\taction: CostGuardAction;\n}\n\n/** Decide whether the projected turn cost trips the guard. Disabled (`maxTurnUsd<=0`) is never `over`. */\nexport function evaluateCostGuard(estUsd: number, settings: CostGuardSettings): CostGuardDecision {\n\tconst enabled = settings.maxTurnUsd > 0;\n\treturn {\n\t\tover: enabled && estUsd > settings.maxTurnUsd,\n\t\testUsd,\n\t\tthresholdUsd: settings.maxTurnUsd,\n\t\taction: settings.action,\n\t};\n}\n\n/** Reasoning levels in descending cost order, used to pick the next-cheaper level on a downgrade. */\nconst REASONING_LADDER = [\"xhigh\", \"high\", \"medium\", \"low\", \"minimal\", \"off\"] as const;\nexport type ReasoningLevel = (typeof REASONING_LADDER)[number];\n\n/**\n * One step down the reasoning ladder (cost reduction) from `current`. Returns `current` unchanged when\n * already at the floor or unrecognized — the guard never raises effort, only lowers it.\n */\nexport function downgradeReasoning(current: string): ReasoningLevel | string {\n\tconst i = REASONING_LADDER.indexOf(current as ReasoningLevel);\n\tif (i < 0) return current;\n\treturn REASONING_LADDER[Math.min(i + 1, REASONING_LADDER.length - 1)];\n}\n"]}
|
package/dist/core/cost-guard.js
CHANGED
|
@@ -17,8 +17,8 @@ export function estimateTurnCostUsd(args) {
|
|
|
17
17
|
const cached = Math.max(0, Math.min(args.cachedInputTokens ?? 0, inputTokens));
|
|
18
18
|
const freshInput = inputTokens - cached;
|
|
19
19
|
const cacheReadRate = cost.cacheRead ?? cost.input;
|
|
20
|
-
const inputUsd = freshInput * cost.input + cached * cacheReadRate;
|
|
21
|
-
const outputUsd = Math.max(0, maxOutputTokens) * cost.output;
|
|
20
|
+
const inputUsd = (freshInput * cost.input + cached * cacheReadRate) / 1_000_000;
|
|
21
|
+
const outputUsd = (Math.max(0, maxOutputTokens) * cost.output) / 1_000_000;
|
|
22
22
|
return inputUsd + outputUsd;
|
|
23
23
|
}
|
|
24
24
|
export const DEFAULT_COST_GUARD_SETTINGS = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost-guard.js","sourceRoot":"","sources":["../../src/core/cost-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAKnC,EAAU;IACV,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/E,MAAM,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;IACxC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC,KAAK,GAAG,MAAM,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"cost-guard.js","sourceRoot":"","sources":["../../src/core/cost-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAKnC,EAAU;IACV,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IACpD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IAC/E,MAAM,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;IACxC,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC;IACnD,MAAM,QAAQ,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,GAAG,MAAM,GAAG,aAAa,CAAC,GAAG,SAAS,CAAC;IAChF,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IAC3E,OAAO,QAAQ,GAAG,SAAS,CAAC;AAAA,CAC5B;AAYD,MAAM,CAAC,MAAM,2BAA2B,GAAsB;IAC7D,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,MAAM;CACd,CAAC;AAUF,0GAA0G;AAC1G,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,QAA2B,EAAqB;IACjG,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC;IACxC,OAAO;QACN,IAAI,EAAE,OAAO,IAAI,MAAM,GAAG,QAAQ,CAAC,UAAU;QAC7C,MAAM;QACN,YAAY,EAAE,QAAQ,CAAC,UAAU;QACjC,MAAM,EAAE,QAAQ,CAAC,MAAM;KACvB,CAAC;AAAA,CACF;AAED,qGAAqG;AACrG,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,CAAU,CAAC;AAGvF;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAA2B;IAC5E,MAAM,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,OAAyB,CAAC,CAAC;IAC9D,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAC1B,OAAO,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;AAAA,CACtE","sourcesContent":["/**\n * Proactive per-turn token cost guard (Hermes-parity superiority item #34).\n *\n * Hermes (and pi today) only react to context growth by compressing AFTER it's expensive. This estimates\n * the dollar cost of the NEXT LLM call BEFORE it is submitted, so the agent can warn the user or\n * automatically reduce reasoning effort before a runaway billing spike — a proactive ceiling, not a\n * reactive cleanup. Pure functions: no I/O, fully testable.\n */\n\n/** Per-million-token USD prices, as carried on `Model.cost`. */\nexport interface ModelTokenCost {\n\tinput: number;\n\toutput: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n}\n\n/**\n * Estimate the USD cost of one turn: the whole current context is billed as input, plus up to\n * `maxOutputTokens` of output. `cachedInputTokens` (prefix-cache hits) are billed at the cheaper\n * cache-read rate instead of the full input rate. This is an UPPER bound on the turn (it assumes the\n * model emits its full output budget), which is what a spending ceiling should bound against.\n */\nexport function estimateTurnCostUsd(args: {\n\tinputTokens: number;\n\tmaxOutputTokens: number;\n\tcost: ModelTokenCost;\n\tcachedInputTokens?: number;\n}): number {\n\tconst { inputTokens, maxOutputTokens, cost } = args;\n\tconst cached = Math.max(0, Math.min(args.cachedInputTokens ?? 0, inputTokens));\n\tconst freshInput = inputTokens - cached;\n\tconst cacheReadRate = cost.cacheRead ?? cost.input;\n\tconst inputUsd = (freshInput * cost.input + cached * cacheReadRate) / 1_000_000;\n\tconst outputUsd = (Math.max(0, maxOutputTokens) * cost.output) / 1_000_000;\n\treturn inputUsd + outputUsd;\n}\n\n/** What to do when a turn's projected cost exceeds the threshold. */\nexport type CostGuardAction = \"warn\" | \"downgrade\";\n\nexport interface CostGuardSettings {\n\t/** Per-turn USD ceiling. `0` (default) disables the guard entirely. */\n\tmaxTurnUsd: number;\n\t/** Over the ceiling: `warn` (surface a notice) or `downgrade` (also reduce reasoning effort). */\n\taction: CostGuardAction;\n}\n\nexport const DEFAULT_COST_GUARD_SETTINGS: CostGuardSettings = {\n\tmaxTurnUsd: 0,\n\taction: \"warn\",\n};\n\nexport interface CostGuardDecision {\n\t/** True when the guard is enabled AND the projected cost exceeds the ceiling. */\n\tover: boolean;\n\testUsd: number;\n\tthresholdUsd: number;\n\taction: CostGuardAction;\n}\n\n/** Decide whether the projected turn cost trips the guard. Disabled (`maxTurnUsd<=0`) is never `over`. */\nexport function evaluateCostGuard(estUsd: number, settings: CostGuardSettings): CostGuardDecision {\n\tconst enabled = settings.maxTurnUsd > 0;\n\treturn {\n\t\tover: enabled && estUsd > settings.maxTurnUsd,\n\t\testUsd,\n\t\tthresholdUsd: settings.maxTurnUsd,\n\t\taction: settings.action,\n\t};\n}\n\n/** Reasoning levels in descending cost order, used to pick the next-cheaper level on a downgrade. */\nconst REASONING_LADDER = [\"xhigh\", \"high\", \"medium\", \"low\", \"minimal\", \"off\"] as const;\nexport type ReasoningLevel = (typeof REASONING_LADDER)[number];\n\n/**\n * One step down the reasoning ladder (cost reduction) from `current`. Returns `current` unchanged when\n * already at the floor or unrecognized — the guard never raises effort, only lowers it.\n */\nexport function downgradeReasoning(current: string): ReasoningLevel | string {\n\tconst i = REASONING_LADDER.indexOf(current as ReasoningLevel);\n\tif (i < 0) return current;\n\treturn REASONING_LADDER[Math.min(i + 1, REASONING_LADDER.length - 1)];\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ThinkingLevel } from "@caupulican/pi-agent-core";
|
|
2
2
|
import type { ModelRouterSettings, ResourceProfileSettings, Settings } from "./settings-manager.ts";
|
|
3
|
-
export type ProfileSource = "global-settings" | "project-settings" | "profile-file" | "directory-overlay" | "inline" | "embedded" | "bundle";
|
|
3
|
+
export type ProfileSource = "global-settings" | "project-settings" | "external-settings" | "profile-file" | "directory-overlay" | "inline" | "embedded" | "bundle";
|
|
4
4
|
export interface NormalizedProfile {
|
|
5
5
|
name: string;
|
|
6
6
|
description?: string;
|
|
@@ -38,6 +38,7 @@ export declare class ProfileRegistry {
|
|
|
38
38
|
resolveProfileRef(ref: string, fromDir: string): NormalizedProfile | undefined;
|
|
39
39
|
private collectCandidates;
|
|
40
40
|
private loadProfileFiles;
|
|
41
|
+
private loadExternalSettingsProfiles;
|
|
41
42
|
private loadProfileFile;
|
|
42
43
|
}
|
|
43
44
|
//# sourceMappingURL=profile-registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-registry.d.ts","sourceRoot":"","sources":["../../src/core/profile-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,KAAK,EACX,mBAAmB,EAEnB,uBAAuB,EACvB,QAAQ,EACR,MAAM,uBAAuB,CAAC;AAG/B,MAAM,MAAM,aAAa,GACtB,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,mBAAmB,GACnB,QAAQ,GACR,UAAU,GACV,QAAQ,CAAC;AAEZ,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACzC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACtC,cAAc,EAAE,QAAQ,CAAC;IACzB,eAAe,EAAE,QAAQ,CAAC;IAC1B,wBAAwB,EAAE,QAAQ,CAAC;IACnC,gCAAgC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IAC1E,oCAAoC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAkJD,qBAAa,eAAe;IAC3B,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,WAAW,CAAmC;IAEtD,YAAY,OAAO,EAAE,sBAAsB,EAE1C;IAED,eAAe,IAAI,yBAAyB,EAAE,CAG7C;IAED,YAAY,IAAI,iBAAiB,EAAE,CAgBlC;IAED,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAItD;IAED,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAQ7E;IAED,OAAO,CAAC,iBAAiB;IA8BzB,OAAO,CAAC,gBAAgB;IA8CxB,OAAO,CAAC,eAAe;CAuBvB","sourcesContent":["import type { ThinkingLevel } from \"@caupulican/pi-agent-core\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { isValidThinkingLevel } from \"../cli/args.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { mergeResourceProfileSettings } from \"./resource-profile-blocks.ts\";\nimport type {\n\tModelRouterSettings,\n\tResourceProfileKind,\n\tResourceProfileSettings,\n\tSettings,\n} from \"./settings-manager.ts\";\nimport { validateSkillName } from \"./skills.ts\";\n\nexport type ProfileSource =\n\t| \"global-settings\"\n\t| \"project-settings\"\n\t| \"profile-file\"\n\t| \"directory-overlay\"\n\t| \"inline\"\n\t| \"embedded\"\n\t| \"bundle\";\n\nexport interface NormalizedProfile {\n\tname: string;\n\tdescription?: string;\n\tmodel?: string;\n\tthinking?: ThinkingLevel;\n\tmodelRouter?: ModelRouterSettings;\n\t/** Situational identity injected into the system prompt while this profile is active (R6). */\n\tsoul?: string;\n\tresources: ResourceProfileSettings;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n}\n\nexport interface ProfileRegistryDiagnostic {\n\tsource: ProfileSource;\n\tpath?: string;\n\tmessage: string;\n}\n\nexport interface ProfileRegistryOptions {\n\tglobalSettings: Settings;\n\tprojectSettings: Settings;\n\tdirectoryProfileSettings: Settings;\n\tinlineResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tdiscoveredResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tprofilesDir?: string;\n\texternalResourceRoots?: string[];\n}\n\nconst RESOURCE_PROFILE_KINDS: ResourceProfileKind[] = [\"extensions\", \"skills\", \"prompts\", \"themes\", \"agents\", \"tools\"];\n\ninterface ProfileCandidate {\n\tprofile: NormalizedProfile;\n\tprecedence: number;\n\torder: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction asStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst strings = value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n\treturn strings.length > 0 ? strings : undefined;\n}\n\nfunction shouldResolveAgainstBaseDir(pattern: string): boolean {\n\treturn pattern.startsWith(\"./\") || pattern.startsWith(\"../\");\n}\n\nfunction normalizePattern(pattern: string, baseDir: string | undefined): string {\n\tconst trimmed = pattern.trim();\n\tif (!baseDir || !shouldResolveAgainstBaseDir(trimmed)) return trimmed;\n\treturn resolvePath(trimmed, baseDir, { trim: true });\n}\n\nfunction normalizeStringArray(value: unknown, baseDir: string | undefined): string[] | undefined {\n\tconst strings = asStringArray(value);\n\tif (!strings) return undefined;\n\treturn strings.map((pattern) => normalizePattern(pattern, baseDir));\n}\n\nfunction normalizeResourceProfileSettings(value: unknown, baseDir: string | undefined): ResourceProfileSettings {\n\tif (!isRecord(value)) {\n\t\tthrow new Error(\"resources must be an object\");\n\t}\n\tconst result: ResourceProfileSettings = {};\n\tfor (const kind of RESOURCE_PROFILE_KINDS) {\n\t\tconst filterValue = value[kind];\n\t\tif (filterValue === undefined) continue;\n\t\tif (!isRecord(filterValue)) {\n\t\t\tthrow new Error(`${kind} filter must be an object`);\n\t\t}\n\t\tconst allow = normalizeStringArray(filterValue.allow, baseDir);\n\t\tconst block = normalizeStringArray(filterValue.block, baseDir);\n\t\tresult[kind] = { allow, block };\n\t}\n\treturn result;\n}\n\nfunction validateProfileName(name: string): string[] {\n\treturn validateSkillName(name);\n}\n\nfunction normalizeThinking(value: unknown): ThinkingLevel | undefined {\n\tconst thinking = asNonEmptyString(value);\n\tif (!thinking) return undefined;\n\tif (!isValidThinkingLevel(thinking)) {\n\t\tthrow new Error(`thinking must be one of off, minimal, low, medium, high, xhigh`);\n\t}\n\treturn thinking;\n}\n\nfunction normalizeModelRouterSettings(value: unknown): ModelRouterSettings | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst settings: ModelRouterSettings = {};\n\tif (typeof value.enabled === \"boolean\") settings.enabled = value.enabled;\n\tfor (const key of [\"cheapModel\", \"expensiveModel\", \"learningModel\"] as const) {\n\t\tconst candidate = asNonEmptyString(value[key]);\n\t\tif (candidate) settings[key] = candidate;\n\t}\n\treturn Object.keys(settings).length > 0 ? settings : undefined;\n}\n\nfunction normalizeWrapperProfile(options: {\n\tvalue: unknown;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n\tfallbackName?: string;\n}): NormalizedProfile {\n\tif (!isRecord(options.value)) {\n\t\tthrow new Error(\"profile JSON must be an object\");\n\t}\n\tconst name = asNonEmptyString(options.value.name) ?? options.fallbackName;\n\tif (!name) {\n\t\tthrow new Error(\"profile name is required\");\n\t}\n\tconst nameErrors = validateProfileName(name);\n\tif (nameErrors.length > 0) {\n\t\tthrow new Error(`invalid profile name \"${name}\": ${nameErrors.join(\", \")}`);\n\t}\n\tconst resources = normalizeResourceProfileSettings(options.value.resources ?? {}, options.baseDir);\n\tconst description = asNonEmptyString(options.value.description);\n\tconst model = asNonEmptyString(options.value.model);\n\tconst thinking = normalizeThinking(options.value.thinking);\n\tconst modelRouter = normalizeModelRouterSettings(options.value.modelRouter);\n\tconst soul = asNonEmptyString(options.value.soul);\n\treturn {\n\t\tname,\n\t\tdescription,\n\t\tmodel,\n\t\tthinking,\n\t\tmodelRouter,\n\t\tsoul,\n\t\tresources,\n\t\tsource: options.source,\n\t\tsourcePath: options.sourcePath,\n\t\tbaseDir: options.baseDir,\n\t};\n}\n\nfunction normalizeSettingsProfiles(\n\tsettings: Settings,\n\tsource: ProfileSource,\n): Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> {\n\tconst profiles: Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> = [];\n\tfor (const [name, resources] of Object.entries(settings.resourceProfiles ?? {})) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({ name, resources: mergeResourceProfileSettings(undefined, resources) });\n\t}\n\treturn profiles.map((profile) => ({ ...profile, source }));\n}\n\nfunction normalizeDefinitions(\n\tdefinitions: Record<string, ResourceProfileSettings>,\n\tsource: ProfileSource,\n): NormalizedProfile[] {\n\tconst profiles: NormalizedProfile[] = [];\n\tfor (const [name, resources] of Object.entries(definitions)) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({ name, resources: mergeResourceProfileSettings(undefined, resources), source });\n\t}\n\treturn profiles;\n}\n\nexport class ProfileRegistry {\n\tprivate options: ProfileRegistryOptions;\n\tprivate diagnostics: ProfileRegistryDiagnostic[] = [];\n\n\tconstructor(options: ProfileRegistryOptions) {\n\t\tthis.options = options;\n\t}\n\n\tlistDiagnostics(): ProfileRegistryDiagnostic[] {\n\t\tthis.collectCandidates();\n\t\treturn [...this.diagnostics];\n\t}\n\n\tlistProfiles(): NormalizedProfile[] {\n\t\tconst candidates = this.collectCandidates();\n\t\tconst winners = new Map<string, ProfileCandidate>();\n\t\tfor (const candidate of candidates) {\n\t\t\tconst existing = winners.get(candidate.profile.name);\n\t\t\tif (\n\t\t\t\t!existing ||\n\t\t\t\tcandidate.precedence < existing.precedence ||\n\t\t\t\t(candidate.precedence === existing.precedence && candidate.order < existing.order)\n\t\t\t) {\n\t\t\t\twinners.set(candidate.profile.name, candidate);\n\t\t\t}\n\t\t}\n\t\treturn Array.from(winners.values())\n\t\t\t.sort((a, b) => a.profile.name.localeCompare(b.profile.name))\n\t\t\t.map((candidate) => candidate.profile);\n\t}\n\n\tgetProfile(name: string): NormalizedProfile | undefined {\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) return undefined;\n\t\treturn this.listProfiles().find((profile) => profile.name === trimmed);\n\t}\n\n\tresolveProfileRef(ref: string, fromDir: string): NormalizedProfile | undefined {\n\t\tconst trimmed = ref.trim();\n\t\tif (!trimmed) return undefined;\n\t\tif (trimmed.startsWith(\"./\") || trimmed.startsWith(\"../\")) {\n\t\t\tconst sourcePath = resolvePath(trimmed, fromDir, { trim: true });\n\t\t\treturn this.loadProfileFile(sourcePath, \"profile-file\", 0)?.profile;\n\t\t}\n\t\treturn this.getProfile(trimmed);\n\t}\n\n\tprivate collectCandidates(): ProfileCandidate[] {\n\t\tthis.diagnostics = [];\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\t\tconst add = (profile: NormalizedProfile, precedence: number): void => {\n\t\t\tcandidates.push({ profile, precedence, order: order++ });\n\t\t};\n\n\t\tfor (const profile of normalizeDefinitions(this.options.inlineResourceProfileDefinitions, \"inline\")) {\n\t\t\tadd(profile, 1);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.directoryProfileSettings, \"directory-overlay\")) {\n\t\t\tadd({ ...profile, source: \"directory-overlay\" }, 2);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.projectSettings, \"project-settings\")) {\n\t\t\tadd({ ...profile, source: \"project-settings\" }, 3);\n\t\t}\n\t\tfor (const profile of this.loadProfileFiles()) {\n\t\t\tadd(profile.profile, profile.precedence);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.globalSettings, \"global-settings\")) {\n\t\t\tadd({ ...profile, source: \"global-settings\" }, 5);\n\t\t}\n\t\tfor (const profile of normalizeDefinitions(this.options.discoveredResourceProfileDefinitions, \"embedded\")) {\n\t\t\tadd(profile, 6);\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadProfileFiles(): ProfileCandidate[] {\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\n\t\tconst profilesDir = this.options.profilesDir;\n\t\tif (profilesDir && existsSync(profilesDir)) {\n\t\t\ttry {\n\t\t\t\tconst entries = readdirSync(profilesDir)\n\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t.sort();\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst sourcePath = join(profilesDir, entry);\n\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4 });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: profilesDir, message: String(error) });\n\t\t\t}\n\t\t}\n\n\t\tconst externalRoots = this.options.externalResourceRoots ?? [];\n\t\tfor (const root of externalRoots) {\n\t\t\tconst extProfilesDir = join(root, \"profiles\");\n\t\t\tif (existsSync(extProfilesDir)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst entries = readdirSync(extProfilesDir)\n\t\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t\t.sort();\n\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\tconst sourcePath = join(extProfilesDir, entry);\n\t\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4.1 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: extProfilesDir, message: String(error) });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadProfileFile(sourcePath: string, source: ProfileSource, order: number): ProfileCandidate | undefined {\n\t\ttry {\n\t\t\tconst stats = statSync(sourcePath);\n\t\t\tif (!stats.isFile()) return undefined;\n\t\t\tconst parsed = JSON.parse(readFileSync(sourcePath, \"utf-8\"));\n\t\t\tconst fallbackName = basename(sourcePath, \".json\");\n\t\t\treturn {\n\t\t\t\tprofile: normalizeWrapperProfile({\n\t\t\t\t\tvalue: parsed,\n\t\t\t\t\tsource,\n\t\t\t\t\tsourcePath: resolve(sourcePath),\n\t\t\t\t\tbaseDir: dirname(resolve(sourcePath)),\n\t\t\t\t\tfallbackName,\n\t\t\t\t}),\n\t\t\t\tprecedence: 0,\n\t\t\t\torder,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthis.diagnostics.push({ source, path: sourcePath, message });\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"profile-registry.d.ts","sourceRoot":"","sources":["../../src/core/profile-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAM/D,OAAO,KAAK,EACX,mBAAmB,EAEnB,uBAAuB,EACvB,QAAQ,EACR,MAAM,uBAAuB,CAAC;AAG/B,MAAM,MAAM,aAAa,GACtB,iBAAiB,GACjB,kBAAkB,GAClB,mBAAmB,GACnB,cAAc,GACd,mBAAmB,GACnB,QAAQ,GACR,UAAU,GACV,QAAQ,CAAC;AAEZ,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,8FAA8F;IAC9F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,uBAAuB,CAAC;IACnC,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,yBAAyB;IACzC,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,sBAAsB;IACtC,cAAc,EAAE,QAAQ,CAAC;IACzB,eAAe,EAAE,QAAQ,CAAC;IAC1B,wBAAwB,EAAE,QAAQ,CAAC;IACnC,gCAAgC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IAC1E,oCAAoC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAyKD,qBAAa,eAAe;IAC3B,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,WAAW,CAAmC;IAEtD,YAAY,OAAO,EAAE,sBAAsB,EAE1C;IAED,eAAe,IAAI,yBAAyB,EAAE,CAG7C;IAED,YAAY,IAAI,iBAAiB,EAAE,CAgBlC;IAED,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAItD;IAED,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAQ7E;IAED,OAAO,CAAC,iBAAiB;IAiCzB,OAAO,CAAC,gBAAgB;IA8CxB,OAAO,CAAC,4BAA4B;IAQpC,OAAO,CAAC,eAAe;CAuBvB","sourcesContent":["import type { ThinkingLevel } from \"@caupulican/pi-agent-core\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { isValidThinkingLevel } from \"../cli/args.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { mergeResourceProfileSettings } from \"./resource-profile-blocks.ts\";\nimport type {\n\tModelRouterSettings,\n\tResourceProfileKind,\n\tResourceProfileSettings,\n\tSettings,\n} from \"./settings-manager.ts\";\nimport { validateSkillName } from \"./skills.ts\";\n\nexport type ProfileSource =\n\t| \"global-settings\"\n\t| \"project-settings\"\n\t| \"external-settings\"\n\t| \"profile-file\"\n\t| \"directory-overlay\"\n\t| \"inline\"\n\t| \"embedded\"\n\t| \"bundle\";\n\nexport interface NormalizedProfile {\n\tname: string;\n\tdescription?: string;\n\tmodel?: string;\n\tthinking?: ThinkingLevel;\n\tmodelRouter?: ModelRouterSettings;\n\t/** Situational identity injected into the system prompt while this profile is active (R6). */\n\tsoul?: string;\n\tresources: ResourceProfileSettings;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n}\n\nexport interface ProfileRegistryDiagnostic {\n\tsource: ProfileSource;\n\tpath?: string;\n\tmessage: string;\n}\n\nexport interface ProfileRegistryOptions {\n\tglobalSettings: Settings;\n\tprojectSettings: Settings;\n\tdirectoryProfileSettings: Settings;\n\tinlineResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tdiscoveredResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tprofilesDir?: string;\n\texternalResourceRoots?: string[];\n}\n\nconst RESOURCE_PROFILE_KINDS: ResourceProfileKind[] = [\"extensions\", \"skills\", \"prompts\", \"themes\", \"agents\", \"tools\"];\n\ninterface ProfileCandidate {\n\tprofile: NormalizedProfile;\n\tprecedence: number;\n\torder: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction asStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst strings = value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n\treturn strings.length > 0 ? strings : undefined;\n}\n\nfunction shouldResolveAgainstBaseDir(pattern: string): boolean {\n\treturn pattern.startsWith(\"./\") || pattern.startsWith(\"../\");\n}\n\nfunction normalizePattern(pattern: string, baseDir: string | undefined): string {\n\tconst trimmed = pattern.trim();\n\tif (!baseDir || !shouldResolveAgainstBaseDir(trimmed)) return trimmed;\n\treturn resolvePath(trimmed, baseDir, { trim: true });\n}\n\nfunction normalizeStringArray(value: unknown, baseDir: string | undefined): string[] | undefined {\n\tconst strings = asStringArray(value);\n\tif (!strings) return undefined;\n\treturn strings.map((pattern) => normalizePattern(pattern, baseDir));\n}\n\nfunction normalizeResourceProfileSettings(value: unknown, baseDir: string | undefined): ResourceProfileSettings {\n\tif (!isRecord(value)) {\n\t\tthrow new Error(\"resources must be an object\");\n\t}\n\tconst result: ResourceProfileSettings = {};\n\tfor (const kind of RESOURCE_PROFILE_KINDS) {\n\t\tconst filterValue = value[kind];\n\t\tif (filterValue === undefined) continue;\n\t\tif (!isRecord(filterValue)) {\n\t\t\tthrow new Error(`${kind} filter must be an object`);\n\t\t}\n\t\tconst allow = normalizeStringArray(filterValue.allow, baseDir);\n\t\tconst block = normalizeStringArray(filterValue.block, baseDir);\n\t\tresult[kind] = { allow, block };\n\t}\n\treturn result;\n}\n\nfunction validateProfileName(name: string): string[] {\n\treturn validateSkillName(name);\n}\n\nfunction normalizeThinking(value: unknown): ThinkingLevel | undefined {\n\tconst thinking = asNonEmptyString(value);\n\tif (!thinking) return undefined;\n\tif (!isValidThinkingLevel(thinking)) {\n\t\tthrow new Error(`thinking must be one of off, minimal, low, medium, high, xhigh`);\n\t}\n\treturn thinking;\n}\n\nfunction normalizeModelRouterSettings(value: unknown): ModelRouterSettings | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst settings: ModelRouterSettings = {};\n\tif (typeof value.enabled === \"boolean\") settings.enabled = value.enabled;\n\tfor (const key of [\"cheapModel\", \"expensiveModel\", \"learningModel\"] as const) {\n\t\tconst candidate = asNonEmptyString(value[key]);\n\t\tif (candidate) settings[key] = candidate;\n\t}\n\treturn Object.keys(settings).length > 0 ? settings : undefined;\n}\n\nfunction normalizeWrapperProfile(options: {\n\tvalue: unknown;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n\tfallbackName?: string;\n}): NormalizedProfile {\n\tif (!isRecord(options.value)) {\n\t\tthrow new Error(\"profile JSON must be an object\");\n\t}\n\tconst name = asNonEmptyString(options.value.name) ?? options.fallbackName;\n\tif (!name) {\n\t\tthrow new Error(\"profile name is required\");\n\t}\n\tconst nameErrors = validateProfileName(name);\n\tif (nameErrors.length > 0) {\n\t\tthrow new Error(`invalid profile name \"${name}\": ${nameErrors.join(\", \")}`);\n\t}\n\tconst resources = normalizeResourceProfileSettings(options.value.resources ?? {}, options.baseDir);\n\tconst description = asNonEmptyString(options.value.description);\n\tconst model = asNonEmptyString(options.value.model);\n\tconst thinking = normalizeThinking(options.value.thinking);\n\tconst modelRouter = normalizeModelRouterSettings(options.value.modelRouter);\n\tconst soul = asNonEmptyString(options.value.soul);\n\treturn {\n\t\tname,\n\t\tdescription,\n\t\tmodel,\n\t\tthinking,\n\t\tmodelRouter,\n\t\tsoul,\n\t\tresources,\n\t\tsource: options.source,\n\t\tsourcePath: options.sourcePath,\n\t\tbaseDir: options.baseDir,\n\t};\n}\n\nfunction normalizeSettingsProfiles(\n\tsettings: Settings,\n\tsource: ProfileSource,\n\tbaseDir?: string,\n\tsourcePath?: string,\n): Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> {\n\tconst profiles: Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> = [];\n\tfor (const [name, resources] of Object.entries(settings.resourceProfiles ?? {})) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({\n\t\t\tname,\n\t\t\tresources: mergeResourceProfileSettings(undefined, resources),\n\t\t\tsourcePath,\n\t\t\tbaseDir,\n\t\t});\n\t}\n\treturn profiles.map((profile) => ({ ...profile, source }));\n}\n\nfunction loadSettingsFileProfiles(sourcePath: string, source: ProfileSource): NormalizedProfile[] {\n\ttry {\n\t\tconst stats = statSync(sourcePath);\n\t\tif (!stats.isFile()) return [];\n\t\tconst parsed = JSON.parse(readFileSync(sourcePath, \"utf-8\")) as Settings;\n\t\treturn normalizeSettingsProfiles(parsed, source, dirname(resolve(sourcePath)), resolve(sourcePath)).map(\n\t\t\t(profile) => ({\n\t\t\t\t...profile,\n\t\t\t\tsource,\n\t\t\t}),\n\t\t);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction normalizeDefinitions(\n\tdefinitions: Record<string, ResourceProfileSettings>,\n\tsource: ProfileSource,\n): NormalizedProfile[] {\n\tconst profiles: NormalizedProfile[] = [];\n\tfor (const [name, resources] of Object.entries(definitions)) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({ name, resources: mergeResourceProfileSettings(undefined, resources), source });\n\t}\n\treturn profiles;\n}\n\nexport class ProfileRegistry {\n\tprivate options: ProfileRegistryOptions;\n\tprivate diagnostics: ProfileRegistryDiagnostic[] = [];\n\n\tconstructor(options: ProfileRegistryOptions) {\n\t\tthis.options = options;\n\t}\n\n\tlistDiagnostics(): ProfileRegistryDiagnostic[] {\n\t\tthis.collectCandidates();\n\t\treturn [...this.diagnostics];\n\t}\n\n\tlistProfiles(): NormalizedProfile[] {\n\t\tconst candidates = this.collectCandidates();\n\t\tconst winners = new Map<string, ProfileCandidate>();\n\t\tfor (const candidate of candidates) {\n\t\t\tconst existing = winners.get(candidate.profile.name);\n\t\t\tif (\n\t\t\t\t!existing ||\n\t\t\t\tcandidate.precedence < existing.precedence ||\n\t\t\t\t(candidate.precedence === existing.precedence && candidate.order < existing.order)\n\t\t\t) {\n\t\t\t\twinners.set(candidate.profile.name, candidate);\n\t\t\t}\n\t\t}\n\t\treturn Array.from(winners.values())\n\t\t\t.sort((a, b) => a.profile.name.localeCompare(b.profile.name))\n\t\t\t.map((candidate) => candidate.profile);\n\t}\n\n\tgetProfile(name: string): NormalizedProfile | undefined {\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) return undefined;\n\t\treturn this.listProfiles().find((profile) => profile.name === trimmed);\n\t}\n\n\tresolveProfileRef(ref: string, fromDir: string): NormalizedProfile | undefined {\n\t\tconst trimmed = ref.trim();\n\t\tif (!trimmed) return undefined;\n\t\tif (trimmed.startsWith(\"./\") || trimmed.startsWith(\"../\")) {\n\t\t\tconst sourcePath = resolvePath(trimmed, fromDir, { trim: true });\n\t\t\treturn this.loadProfileFile(sourcePath, \"profile-file\", 0)?.profile;\n\t\t}\n\t\treturn this.getProfile(trimmed);\n\t}\n\n\tprivate collectCandidates(): ProfileCandidate[] {\n\t\tthis.diagnostics = [];\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\t\tconst add = (profile: NormalizedProfile, precedence: number): void => {\n\t\t\tcandidates.push({ profile, precedence, order: order++ });\n\t\t};\n\n\t\tfor (const profile of normalizeDefinitions(this.options.inlineResourceProfileDefinitions, \"inline\")) {\n\t\t\tadd(profile, 1);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.directoryProfileSettings, \"directory-overlay\")) {\n\t\t\tadd({ ...profile, source: \"directory-overlay\" }, 2);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.projectSettings, \"project-settings\")) {\n\t\t\tadd({ ...profile, source: \"project-settings\" }, 3);\n\t\t}\n\t\tfor (const profile of this.loadProfileFiles()) {\n\t\t\tadd(profile.profile, profile.precedence);\n\t\t}\n\t\tfor (const profile of this.loadExternalSettingsProfiles()) {\n\t\t\tadd(profile, 4.2);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.globalSettings, \"global-settings\")) {\n\t\t\tadd({ ...profile, source: \"global-settings\" }, 5);\n\t\t}\n\t\tfor (const profile of normalizeDefinitions(this.options.discoveredResourceProfileDefinitions, \"embedded\")) {\n\t\t\tadd(profile, 6);\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadProfileFiles(): ProfileCandidate[] {\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\n\t\tconst profilesDir = this.options.profilesDir;\n\t\tif (profilesDir && existsSync(profilesDir)) {\n\t\t\ttry {\n\t\t\t\tconst entries = readdirSync(profilesDir)\n\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t.sort();\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst sourcePath = join(profilesDir, entry);\n\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4 });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: profilesDir, message: String(error) });\n\t\t\t}\n\t\t}\n\n\t\tconst externalRoots = this.options.externalResourceRoots ?? [];\n\t\tfor (const root of externalRoots) {\n\t\t\tconst extProfilesDir = join(root, \"profiles\");\n\t\t\tif (existsSync(extProfilesDir)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst entries = readdirSync(extProfilesDir)\n\t\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t\t.sort();\n\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\tconst sourcePath = join(extProfilesDir, entry);\n\t\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4.1 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: extProfilesDir, message: String(error) });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadExternalSettingsProfiles(): NormalizedProfile[] {\n\t\tconst profiles: NormalizedProfile[] = [];\n\t\tfor (const root of this.options.externalResourceRoots ?? []) {\n\t\t\tprofiles.push(...loadSettingsFileProfiles(join(root, \"settings.json\"), \"external-settings\"));\n\t\t}\n\t\treturn profiles;\n\t}\n\n\tprivate loadProfileFile(sourcePath: string, source: ProfileSource, order: number): ProfileCandidate | undefined {\n\t\ttry {\n\t\t\tconst stats = statSync(sourcePath);\n\t\t\tif (!stats.isFile()) return undefined;\n\t\t\tconst parsed = JSON.parse(readFileSync(sourcePath, \"utf-8\"));\n\t\t\tconst fallbackName = basename(sourcePath, \".json\");\n\t\t\treturn {\n\t\t\t\tprofile: normalizeWrapperProfile({\n\t\t\t\t\tvalue: parsed,\n\t\t\t\t\tsource,\n\t\t\t\t\tsourcePath: resolve(sourcePath),\n\t\t\t\t\tbaseDir: dirname(resolve(sourcePath)),\n\t\t\t\t\tfallbackName,\n\t\t\t\t}),\n\t\t\t\tprecedence: 0,\n\t\t\t\torder,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthis.diagnostics.push({ source, path: sourcePath, message });\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n"]}
|
|
@@ -106,16 +106,36 @@ function normalizeWrapperProfile(options) {
|
|
|
106
106
|
baseDir: options.baseDir,
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
|
-
function normalizeSettingsProfiles(settings, source) {
|
|
109
|
+
function normalizeSettingsProfiles(settings, source, baseDir, sourcePath) {
|
|
110
110
|
const profiles = [];
|
|
111
111
|
for (const [name, resources] of Object.entries(settings.resourceProfiles ?? {})) {
|
|
112
112
|
const nameErrors = validateProfileName(name);
|
|
113
113
|
if (nameErrors.length > 0)
|
|
114
114
|
continue;
|
|
115
|
-
profiles.push({
|
|
115
|
+
profiles.push({
|
|
116
|
+
name,
|
|
117
|
+
resources: mergeResourceProfileSettings(undefined, resources),
|
|
118
|
+
sourcePath,
|
|
119
|
+
baseDir,
|
|
120
|
+
});
|
|
116
121
|
}
|
|
117
122
|
return profiles.map((profile) => ({ ...profile, source }));
|
|
118
123
|
}
|
|
124
|
+
function loadSettingsFileProfiles(sourcePath, source) {
|
|
125
|
+
try {
|
|
126
|
+
const stats = statSync(sourcePath);
|
|
127
|
+
if (!stats.isFile())
|
|
128
|
+
return [];
|
|
129
|
+
const parsed = JSON.parse(readFileSync(sourcePath, "utf-8"));
|
|
130
|
+
return normalizeSettingsProfiles(parsed, source, dirname(resolve(sourcePath)), resolve(sourcePath)).map((profile) => ({
|
|
131
|
+
...profile,
|
|
132
|
+
source,
|
|
133
|
+
}));
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return [];
|
|
137
|
+
}
|
|
138
|
+
}
|
|
119
139
|
function normalizeDefinitions(definitions, source) {
|
|
120
140
|
const profiles = [];
|
|
121
141
|
for (const [name, resources] of Object.entries(definitions)) {
|
|
@@ -186,6 +206,9 @@ export class ProfileRegistry {
|
|
|
186
206
|
for (const profile of this.loadProfileFiles()) {
|
|
187
207
|
add(profile.profile, profile.precedence);
|
|
188
208
|
}
|
|
209
|
+
for (const profile of this.loadExternalSettingsProfiles()) {
|
|
210
|
+
add(profile, 4.2);
|
|
211
|
+
}
|
|
189
212
|
for (const profile of normalizeSettingsProfiles(this.options.globalSettings, "global-settings")) {
|
|
190
213
|
add({ ...profile, source: "global-settings" }, 5);
|
|
191
214
|
}
|
|
@@ -238,6 +261,13 @@ export class ProfileRegistry {
|
|
|
238
261
|
}
|
|
239
262
|
return candidates;
|
|
240
263
|
}
|
|
264
|
+
loadExternalSettingsProfiles() {
|
|
265
|
+
const profiles = [];
|
|
266
|
+
for (const root of this.options.externalResourceRoots ?? []) {
|
|
267
|
+
profiles.push(...loadSettingsFileProfiles(join(root, "settings.json"), "external-settings"));
|
|
268
|
+
}
|
|
269
|
+
return profiles;
|
|
270
|
+
}
|
|
241
271
|
loadProfileFile(sourcePath, source, order) {
|
|
242
272
|
try {
|
|
243
273
|
const stats = statSync(sourcePath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile-registry.js","sourceRoot":"","sources":["../../src/core/profile-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@caupulican/pi-agent-core\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { isValidThinkingLevel } from \"../cli/args.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { mergeResourceProfileSettings } from \"./resource-profile-blocks.ts\";\nimport type {\n\tModelRouterSettings,\n\tResourceProfileKind,\n\tResourceProfileSettings,\n\tSettings,\n} from \"./settings-manager.ts\";\nimport { validateSkillName } from \"./skills.ts\";\n\nexport type ProfileSource =\n\t| \"global-settings\"\n\t| \"project-settings\"\n\t| \"profile-file\"\n\t| \"directory-overlay\"\n\t| \"inline\"\n\t| \"embedded\"\n\t| \"bundle\";\n\nexport interface NormalizedProfile {\n\tname: string;\n\tdescription?: string;\n\tmodel?: string;\n\tthinking?: ThinkingLevel;\n\tmodelRouter?: ModelRouterSettings;\n\t/** Situational identity injected into the system prompt while this profile is active (R6). */\n\tsoul?: string;\n\tresources: ResourceProfileSettings;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n}\n\nexport interface ProfileRegistryDiagnostic {\n\tsource: ProfileSource;\n\tpath?: string;\n\tmessage: string;\n}\n\nexport interface ProfileRegistryOptions {\n\tglobalSettings: Settings;\n\tprojectSettings: Settings;\n\tdirectoryProfileSettings: Settings;\n\tinlineResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tdiscoveredResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tprofilesDir?: string;\n\texternalResourceRoots?: string[];\n}\n\nconst RESOURCE_PROFILE_KINDS: ResourceProfileKind[] = [\"extensions\", \"skills\", \"prompts\", \"themes\", \"agents\", \"tools\"];\n\ninterface ProfileCandidate {\n\tprofile: NormalizedProfile;\n\tprecedence: number;\n\torder: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction asStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst strings = value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n\treturn strings.length > 0 ? strings : undefined;\n}\n\nfunction shouldResolveAgainstBaseDir(pattern: string): boolean {\n\treturn pattern.startsWith(\"./\") || pattern.startsWith(\"../\");\n}\n\nfunction normalizePattern(pattern: string, baseDir: string | undefined): string {\n\tconst trimmed = pattern.trim();\n\tif (!baseDir || !shouldResolveAgainstBaseDir(trimmed)) return trimmed;\n\treturn resolvePath(trimmed, baseDir, { trim: true });\n}\n\nfunction normalizeStringArray(value: unknown, baseDir: string | undefined): string[] | undefined {\n\tconst strings = asStringArray(value);\n\tif (!strings) return undefined;\n\treturn strings.map((pattern) => normalizePattern(pattern, baseDir));\n}\n\nfunction normalizeResourceProfileSettings(value: unknown, baseDir: string | undefined): ResourceProfileSettings {\n\tif (!isRecord(value)) {\n\t\tthrow new Error(\"resources must be an object\");\n\t}\n\tconst result: ResourceProfileSettings = {};\n\tfor (const kind of RESOURCE_PROFILE_KINDS) {\n\t\tconst filterValue = value[kind];\n\t\tif (filterValue === undefined) continue;\n\t\tif (!isRecord(filterValue)) {\n\t\t\tthrow new Error(`${kind} filter must be an object`);\n\t\t}\n\t\tconst allow = normalizeStringArray(filterValue.allow, baseDir);\n\t\tconst block = normalizeStringArray(filterValue.block, baseDir);\n\t\tresult[kind] = { allow, block };\n\t}\n\treturn result;\n}\n\nfunction validateProfileName(name: string): string[] {\n\treturn validateSkillName(name);\n}\n\nfunction normalizeThinking(value: unknown): ThinkingLevel | undefined {\n\tconst thinking = asNonEmptyString(value);\n\tif (!thinking) return undefined;\n\tif (!isValidThinkingLevel(thinking)) {\n\t\tthrow new Error(`thinking must be one of off, minimal, low, medium, high, xhigh`);\n\t}\n\treturn thinking;\n}\n\nfunction normalizeModelRouterSettings(value: unknown): ModelRouterSettings | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst settings: ModelRouterSettings = {};\n\tif (typeof value.enabled === \"boolean\") settings.enabled = value.enabled;\n\tfor (const key of [\"cheapModel\", \"expensiveModel\", \"learningModel\"] as const) {\n\t\tconst candidate = asNonEmptyString(value[key]);\n\t\tif (candidate) settings[key] = candidate;\n\t}\n\treturn Object.keys(settings).length > 0 ? settings : undefined;\n}\n\nfunction normalizeWrapperProfile(options: {\n\tvalue: unknown;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n\tfallbackName?: string;\n}): NormalizedProfile {\n\tif (!isRecord(options.value)) {\n\t\tthrow new Error(\"profile JSON must be an object\");\n\t}\n\tconst name = asNonEmptyString(options.value.name) ?? options.fallbackName;\n\tif (!name) {\n\t\tthrow new Error(\"profile name is required\");\n\t}\n\tconst nameErrors = validateProfileName(name);\n\tif (nameErrors.length > 0) {\n\t\tthrow new Error(`invalid profile name \"${name}\": ${nameErrors.join(\", \")}`);\n\t}\n\tconst resources = normalizeResourceProfileSettings(options.value.resources ?? {}, options.baseDir);\n\tconst description = asNonEmptyString(options.value.description);\n\tconst model = asNonEmptyString(options.value.model);\n\tconst thinking = normalizeThinking(options.value.thinking);\n\tconst modelRouter = normalizeModelRouterSettings(options.value.modelRouter);\n\tconst soul = asNonEmptyString(options.value.soul);\n\treturn {\n\t\tname,\n\t\tdescription,\n\t\tmodel,\n\t\tthinking,\n\t\tmodelRouter,\n\t\tsoul,\n\t\tresources,\n\t\tsource: options.source,\n\t\tsourcePath: options.sourcePath,\n\t\tbaseDir: options.baseDir,\n\t};\n}\n\nfunction normalizeSettingsProfiles(\n\tsettings: Settings,\n\tsource: ProfileSource,\n): Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> {\n\tconst profiles: Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> = [];\n\tfor (const [name, resources] of Object.entries(settings.resourceProfiles ?? {})) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({ name, resources: mergeResourceProfileSettings(undefined, resources) });\n\t}\n\treturn profiles.map((profile) => ({ ...profile, source }));\n}\n\nfunction normalizeDefinitions(\n\tdefinitions: Record<string, ResourceProfileSettings>,\n\tsource: ProfileSource,\n): NormalizedProfile[] {\n\tconst profiles: NormalizedProfile[] = [];\n\tfor (const [name, resources] of Object.entries(definitions)) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({ name, resources: mergeResourceProfileSettings(undefined, resources), source });\n\t}\n\treturn profiles;\n}\n\nexport class ProfileRegistry {\n\tprivate options: ProfileRegistryOptions;\n\tprivate diagnostics: ProfileRegistryDiagnostic[] = [];\n\n\tconstructor(options: ProfileRegistryOptions) {\n\t\tthis.options = options;\n\t}\n\n\tlistDiagnostics(): ProfileRegistryDiagnostic[] {\n\t\tthis.collectCandidates();\n\t\treturn [...this.diagnostics];\n\t}\n\n\tlistProfiles(): NormalizedProfile[] {\n\t\tconst candidates = this.collectCandidates();\n\t\tconst winners = new Map<string, ProfileCandidate>();\n\t\tfor (const candidate of candidates) {\n\t\t\tconst existing = winners.get(candidate.profile.name);\n\t\t\tif (\n\t\t\t\t!existing ||\n\t\t\t\tcandidate.precedence < existing.precedence ||\n\t\t\t\t(candidate.precedence === existing.precedence && candidate.order < existing.order)\n\t\t\t) {\n\t\t\t\twinners.set(candidate.profile.name, candidate);\n\t\t\t}\n\t\t}\n\t\treturn Array.from(winners.values())\n\t\t\t.sort((a, b) => a.profile.name.localeCompare(b.profile.name))\n\t\t\t.map((candidate) => candidate.profile);\n\t}\n\n\tgetProfile(name: string): NormalizedProfile | undefined {\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) return undefined;\n\t\treturn this.listProfiles().find((profile) => profile.name === trimmed);\n\t}\n\n\tresolveProfileRef(ref: string, fromDir: string): NormalizedProfile | undefined {\n\t\tconst trimmed = ref.trim();\n\t\tif (!trimmed) return undefined;\n\t\tif (trimmed.startsWith(\"./\") || trimmed.startsWith(\"../\")) {\n\t\t\tconst sourcePath = resolvePath(trimmed, fromDir, { trim: true });\n\t\t\treturn this.loadProfileFile(sourcePath, \"profile-file\", 0)?.profile;\n\t\t}\n\t\treturn this.getProfile(trimmed);\n\t}\n\n\tprivate collectCandidates(): ProfileCandidate[] {\n\t\tthis.diagnostics = [];\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\t\tconst add = (profile: NormalizedProfile, precedence: number): void => {\n\t\t\tcandidates.push({ profile, precedence, order: order++ });\n\t\t};\n\n\t\tfor (const profile of normalizeDefinitions(this.options.inlineResourceProfileDefinitions, \"inline\")) {\n\t\t\tadd(profile, 1);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.directoryProfileSettings, \"directory-overlay\")) {\n\t\t\tadd({ ...profile, source: \"directory-overlay\" }, 2);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.projectSettings, \"project-settings\")) {\n\t\t\tadd({ ...profile, source: \"project-settings\" }, 3);\n\t\t}\n\t\tfor (const profile of this.loadProfileFiles()) {\n\t\t\tadd(profile.profile, profile.precedence);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.globalSettings, \"global-settings\")) {\n\t\t\tadd({ ...profile, source: \"global-settings\" }, 5);\n\t\t}\n\t\tfor (const profile of normalizeDefinitions(this.options.discoveredResourceProfileDefinitions, \"embedded\")) {\n\t\t\tadd(profile, 6);\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadProfileFiles(): ProfileCandidate[] {\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\n\t\tconst profilesDir = this.options.profilesDir;\n\t\tif (profilesDir && existsSync(profilesDir)) {\n\t\t\ttry {\n\t\t\t\tconst entries = readdirSync(profilesDir)\n\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t.sort();\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst sourcePath = join(profilesDir, entry);\n\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4 });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: profilesDir, message: String(error) });\n\t\t\t}\n\t\t}\n\n\t\tconst externalRoots = this.options.externalResourceRoots ?? [];\n\t\tfor (const root of externalRoots) {\n\t\t\tconst extProfilesDir = join(root, \"profiles\");\n\t\t\tif (existsSync(extProfilesDir)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst entries = readdirSync(extProfilesDir)\n\t\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t\t.sort();\n\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\tconst sourcePath = join(extProfilesDir, entry);\n\t\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4.1 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: extProfilesDir, message: String(error) });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadProfileFile(sourcePath: string, source: ProfileSource, order: number): ProfileCandidate | undefined {\n\t\ttry {\n\t\t\tconst stats = statSync(sourcePath);\n\t\t\tif (!stats.isFile()) return undefined;\n\t\t\tconst parsed = JSON.parse(readFileSync(sourcePath, \"utf-8\"));\n\t\t\tconst fallbackName = basename(sourcePath, \".json\");\n\t\t\treturn {\n\t\t\t\tprofile: normalizeWrapperProfile({\n\t\t\t\t\tvalue: parsed,\n\t\t\t\t\tsource,\n\t\t\t\t\tsourcePath: resolve(sourcePath),\n\t\t\t\t\tbaseDir: dirname(resolve(sourcePath)),\n\t\t\t\t\tfallbackName,\n\t\t\t\t}),\n\t\t\t\tprecedence: 0,\n\t\t\t\torder,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthis.diagnostics.push({ source, path: sourcePath, message });\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"profile-registry.js","sourceRoot":"","sources":["../../src/core/profile-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@caupulican/pi-agent-core\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"fs\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { isValidThinkingLevel } from \"../cli/args.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport { mergeResourceProfileSettings } from \"./resource-profile-blocks.ts\";\nimport type {\n\tModelRouterSettings,\n\tResourceProfileKind,\n\tResourceProfileSettings,\n\tSettings,\n} from \"./settings-manager.ts\";\nimport { validateSkillName } from \"./skills.ts\";\n\nexport type ProfileSource =\n\t| \"global-settings\"\n\t| \"project-settings\"\n\t| \"external-settings\"\n\t| \"profile-file\"\n\t| \"directory-overlay\"\n\t| \"inline\"\n\t| \"embedded\"\n\t| \"bundle\";\n\nexport interface NormalizedProfile {\n\tname: string;\n\tdescription?: string;\n\tmodel?: string;\n\tthinking?: ThinkingLevel;\n\tmodelRouter?: ModelRouterSettings;\n\t/** Situational identity injected into the system prompt while this profile is active (R6). */\n\tsoul?: string;\n\tresources: ResourceProfileSettings;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n}\n\nexport interface ProfileRegistryDiagnostic {\n\tsource: ProfileSource;\n\tpath?: string;\n\tmessage: string;\n}\n\nexport interface ProfileRegistryOptions {\n\tglobalSettings: Settings;\n\tprojectSettings: Settings;\n\tdirectoryProfileSettings: Settings;\n\tinlineResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tdiscoveredResourceProfileDefinitions: Record<string, ResourceProfileSettings>;\n\tprofilesDir?: string;\n\texternalResourceRoots?: string[];\n}\n\nconst RESOURCE_PROFILE_KINDS: ResourceProfileKind[] = [\"extensions\", \"skills\", \"prompts\", \"themes\", \"agents\", \"tools\"];\n\ninterface ProfileCandidate {\n\tprofile: NormalizedProfile;\n\tprecedence: number;\n\torder: number;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\nfunction asStringArray(value: unknown): string[] | undefined {\n\tif (!Array.isArray(value)) return undefined;\n\tconst strings = value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n\treturn strings.length > 0 ? strings : undefined;\n}\n\nfunction shouldResolveAgainstBaseDir(pattern: string): boolean {\n\treturn pattern.startsWith(\"./\") || pattern.startsWith(\"../\");\n}\n\nfunction normalizePattern(pattern: string, baseDir: string | undefined): string {\n\tconst trimmed = pattern.trim();\n\tif (!baseDir || !shouldResolveAgainstBaseDir(trimmed)) return trimmed;\n\treturn resolvePath(trimmed, baseDir, { trim: true });\n}\n\nfunction normalizeStringArray(value: unknown, baseDir: string | undefined): string[] | undefined {\n\tconst strings = asStringArray(value);\n\tif (!strings) return undefined;\n\treturn strings.map((pattern) => normalizePattern(pattern, baseDir));\n}\n\nfunction normalizeResourceProfileSettings(value: unknown, baseDir: string | undefined): ResourceProfileSettings {\n\tif (!isRecord(value)) {\n\t\tthrow new Error(\"resources must be an object\");\n\t}\n\tconst result: ResourceProfileSettings = {};\n\tfor (const kind of RESOURCE_PROFILE_KINDS) {\n\t\tconst filterValue = value[kind];\n\t\tif (filterValue === undefined) continue;\n\t\tif (!isRecord(filterValue)) {\n\t\t\tthrow new Error(`${kind} filter must be an object`);\n\t\t}\n\t\tconst allow = normalizeStringArray(filterValue.allow, baseDir);\n\t\tconst block = normalizeStringArray(filterValue.block, baseDir);\n\t\tresult[kind] = { allow, block };\n\t}\n\treturn result;\n}\n\nfunction validateProfileName(name: string): string[] {\n\treturn validateSkillName(name);\n}\n\nfunction normalizeThinking(value: unknown): ThinkingLevel | undefined {\n\tconst thinking = asNonEmptyString(value);\n\tif (!thinking) return undefined;\n\tif (!isValidThinkingLevel(thinking)) {\n\t\tthrow new Error(`thinking must be one of off, minimal, low, medium, high, xhigh`);\n\t}\n\treturn thinking;\n}\n\nfunction normalizeModelRouterSettings(value: unknown): ModelRouterSettings | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst settings: ModelRouterSettings = {};\n\tif (typeof value.enabled === \"boolean\") settings.enabled = value.enabled;\n\tfor (const key of [\"cheapModel\", \"expensiveModel\", \"learningModel\"] as const) {\n\t\tconst candidate = asNonEmptyString(value[key]);\n\t\tif (candidate) settings[key] = candidate;\n\t}\n\treturn Object.keys(settings).length > 0 ? settings : undefined;\n}\n\nfunction normalizeWrapperProfile(options: {\n\tvalue: unknown;\n\tsource: ProfileSource;\n\tsourcePath?: string;\n\tbaseDir?: string;\n\tfallbackName?: string;\n}): NormalizedProfile {\n\tif (!isRecord(options.value)) {\n\t\tthrow new Error(\"profile JSON must be an object\");\n\t}\n\tconst name = asNonEmptyString(options.value.name) ?? options.fallbackName;\n\tif (!name) {\n\t\tthrow new Error(\"profile name is required\");\n\t}\n\tconst nameErrors = validateProfileName(name);\n\tif (nameErrors.length > 0) {\n\t\tthrow new Error(`invalid profile name \"${name}\": ${nameErrors.join(\", \")}`);\n\t}\n\tconst resources = normalizeResourceProfileSettings(options.value.resources ?? {}, options.baseDir);\n\tconst description = asNonEmptyString(options.value.description);\n\tconst model = asNonEmptyString(options.value.model);\n\tconst thinking = normalizeThinking(options.value.thinking);\n\tconst modelRouter = normalizeModelRouterSettings(options.value.modelRouter);\n\tconst soul = asNonEmptyString(options.value.soul);\n\treturn {\n\t\tname,\n\t\tdescription,\n\t\tmodel,\n\t\tthinking,\n\t\tmodelRouter,\n\t\tsoul,\n\t\tresources,\n\t\tsource: options.source,\n\t\tsourcePath: options.sourcePath,\n\t\tbaseDir: options.baseDir,\n\t};\n}\n\nfunction normalizeSettingsProfiles(\n\tsettings: Settings,\n\tsource: ProfileSource,\n\tbaseDir?: string,\n\tsourcePath?: string,\n): Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> {\n\tconst profiles: Array<Omit<NormalizedProfile, \"source\"> & { source?: ProfileSource }> = [];\n\tfor (const [name, resources] of Object.entries(settings.resourceProfiles ?? {})) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({\n\t\t\tname,\n\t\t\tresources: mergeResourceProfileSettings(undefined, resources),\n\t\t\tsourcePath,\n\t\t\tbaseDir,\n\t\t});\n\t}\n\treturn profiles.map((profile) => ({ ...profile, source }));\n}\n\nfunction loadSettingsFileProfiles(sourcePath: string, source: ProfileSource): NormalizedProfile[] {\n\ttry {\n\t\tconst stats = statSync(sourcePath);\n\t\tif (!stats.isFile()) return [];\n\t\tconst parsed = JSON.parse(readFileSync(sourcePath, \"utf-8\")) as Settings;\n\t\treturn normalizeSettingsProfiles(parsed, source, dirname(resolve(sourcePath)), resolve(sourcePath)).map(\n\t\t\t(profile) => ({\n\t\t\t\t...profile,\n\t\t\t\tsource,\n\t\t\t}),\n\t\t);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction normalizeDefinitions(\n\tdefinitions: Record<string, ResourceProfileSettings>,\n\tsource: ProfileSource,\n): NormalizedProfile[] {\n\tconst profiles: NormalizedProfile[] = [];\n\tfor (const [name, resources] of Object.entries(definitions)) {\n\t\tconst nameErrors = validateProfileName(name);\n\t\tif (nameErrors.length > 0) continue;\n\t\tprofiles.push({ name, resources: mergeResourceProfileSettings(undefined, resources), source });\n\t}\n\treturn profiles;\n}\n\nexport class ProfileRegistry {\n\tprivate options: ProfileRegistryOptions;\n\tprivate diagnostics: ProfileRegistryDiagnostic[] = [];\n\n\tconstructor(options: ProfileRegistryOptions) {\n\t\tthis.options = options;\n\t}\n\n\tlistDiagnostics(): ProfileRegistryDiagnostic[] {\n\t\tthis.collectCandidates();\n\t\treturn [...this.diagnostics];\n\t}\n\n\tlistProfiles(): NormalizedProfile[] {\n\t\tconst candidates = this.collectCandidates();\n\t\tconst winners = new Map<string, ProfileCandidate>();\n\t\tfor (const candidate of candidates) {\n\t\t\tconst existing = winners.get(candidate.profile.name);\n\t\t\tif (\n\t\t\t\t!existing ||\n\t\t\t\tcandidate.precedence < existing.precedence ||\n\t\t\t\t(candidate.precedence === existing.precedence && candidate.order < existing.order)\n\t\t\t) {\n\t\t\t\twinners.set(candidate.profile.name, candidate);\n\t\t\t}\n\t\t}\n\t\treturn Array.from(winners.values())\n\t\t\t.sort((a, b) => a.profile.name.localeCompare(b.profile.name))\n\t\t\t.map((candidate) => candidate.profile);\n\t}\n\n\tgetProfile(name: string): NormalizedProfile | undefined {\n\t\tconst trimmed = name.trim();\n\t\tif (!trimmed) return undefined;\n\t\treturn this.listProfiles().find((profile) => profile.name === trimmed);\n\t}\n\n\tresolveProfileRef(ref: string, fromDir: string): NormalizedProfile | undefined {\n\t\tconst trimmed = ref.trim();\n\t\tif (!trimmed) return undefined;\n\t\tif (trimmed.startsWith(\"./\") || trimmed.startsWith(\"../\")) {\n\t\t\tconst sourcePath = resolvePath(trimmed, fromDir, { trim: true });\n\t\t\treturn this.loadProfileFile(sourcePath, \"profile-file\", 0)?.profile;\n\t\t}\n\t\treturn this.getProfile(trimmed);\n\t}\n\n\tprivate collectCandidates(): ProfileCandidate[] {\n\t\tthis.diagnostics = [];\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\t\tconst add = (profile: NormalizedProfile, precedence: number): void => {\n\t\t\tcandidates.push({ profile, precedence, order: order++ });\n\t\t};\n\n\t\tfor (const profile of normalizeDefinitions(this.options.inlineResourceProfileDefinitions, \"inline\")) {\n\t\t\tadd(profile, 1);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.directoryProfileSettings, \"directory-overlay\")) {\n\t\t\tadd({ ...profile, source: \"directory-overlay\" }, 2);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.projectSettings, \"project-settings\")) {\n\t\t\tadd({ ...profile, source: \"project-settings\" }, 3);\n\t\t}\n\t\tfor (const profile of this.loadProfileFiles()) {\n\t\t\tadd(profile.profile, profile.precedence);\n\t\t}\n\t\tfor (const profile of this.loadExternalSettingsProfiles()) {\n\t\t\tadd(profile, 4.2);\n\t\t}\n\t\tfor (const profile of normalizeSettingsProfiles(this.options.globalSettings, \"global-settings\")) {\n\t\t\tadd({ ...profile, source: \"global-settings\" }, 5);\n\t\t}\n\t\tfor (const profile of normalizeDefinitions(this.options.discoveredResourceProfileDefinitions, \"embedded\")) {\n\t\t\tadd(profile, 6);\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadProfileFiles(): ProfileCandidate[] {\n\t\tconst candidates: ProfileCandidate[] = [];\n\t\tlet order = 0;\n\n\t\tconst profilesDir = this.options.profilesDir;\n\t\tif (profilesDir && existsSync(profilesDir)) {\n\t\t\ttry {\n\t\t\t\tconst entries = readdirSync(profilesDir)\n\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t.sort();\n\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\tconst sourcePath = join(profilesDir, entry);\n\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4 });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: profilesDir, message: String(error) });\n\t\t\t}\n\t\t}\n\n\t\tconst externalRoots = this.options.externalResourceRoots ?? [];\n\t\tfor (const root of externalRoots) {\n\t\t\tconst extProfilesDir = join(root, \"profiles\");\n\t\t\tif (existsSync(extProfilesDir)) {\n\t\t\t\ttry {\n\t\t\t\t\tconst entries = readdirSync(extProfilesDir)\n\t\t\t\t\t\t.filter((entry) => entry.endsWith(\".json\"))\n\t\t\t\t\t\t.sort();\n\t\t\t\t\tfor (const entry of entries) {\n\t\t\t\t\t\tconst sourcePath = join(extProfilesDir, entry);\n\t\t\t\t\t\tconst loaded = this.loadProfileFile(sourcePath, \"profile-file\", order++);\n\t\t\t\t\t\tif (loaded) {\n\t\t\t\t\t\t\tcandidates.push({ ...loaded, precedence: 4.1 });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.diagnostics.push({ source: \"profile-file\", path: extProfilesDir, message: String(error) });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn candidates;\n\t}\n\n\tprivate loadExternalSettingsProfiles(): NormalizedProfile[] {\n\t\tconst profiles: NormalizedProfile[] = [];\n\t\tfor (const root of this.options.externalResourceRoots ?? []) {\n\t\t\tprofiles.push(...loadSettingsFileProfiles(join(root, \"settings.json\"), \"external-settings\"));\n\t\t}\n\t\treturn profiles;\n\t}\n\n\tprivate loadProfileFile(sourcePath: string, source: ProfileSource, order: number): ProfileCandidate | undefined {\n\t\ttry {\n\t\t\tconst stats = statSync(sourcePath);\n\t\t\tif (!stats.isFile()) return undefined;\n\t\t\tconst parsed = JSON.parse(readFileSync(sourcePath, \"utf-8\"));\n\t\t\tconst fallbackName = basename(sourcePath, \".json\");\n\t\t\treturn {\n\t\t\t\tprofile: normalizeWrapperProfile({\n\t\t\t\t\tvalue: parsed,\n\t\t\t\t\tsource,\n\t\t\t\t\tsourcePath: resolve(sourcePath),\n\t\t\t\t\tbaseDir: dirname(resolve(sourcePath)),\n\t\t\t\t\tfallbackName,\n\t\t\t\t}),\n\t\t\t\tprecedence: 0,\n\t\t\t\torder,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tthis.diagnostics.push({ source, path: sourcePath, message });\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n"]}
|