agents-inc 0.173.0 → 0.174.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dist/{chunk-Q4UNHVPX.js → chunk-3PJZ4QNJ.js} +7 -7
  3. package/dist/{chunk-3N4FSTVX.js → chunk-6PGXTLA4.js} +2 -2
  4. package/dist/{chunk-ITQF35UQ.js → chunk-7BHDKEGK.js} +3 -3
  5. package/dist/{chunk-7OG635DK.js → chunk-AIBVAYHS.js} +6 -2
  6. package/dist/{chunk-7OG635DK.js.map → chunk-AIBVAYHS.js.map} +1 -1
  7. package/dist/{chunk-AARQBW5L.js → chunk-APWMMZOK.js} +30 -23
  8. package/dist/chunk-APWMMZOK.js.map +1 -0
  9. package/dist/{chunk-WVFBBZEP.js → chunk-E45IT3HC.js} +117 -22
  10. package/dist/chunk-E45IT3HC.js.map +1 -0
  11. package/dist/{chunk-F437ICEG.js → chunk-ECPFYHDX.js} +2 -2
  12. package/dist/{chunk-EHJIQDXR.js → chunk-EFXVYQGT.js} +4 -4
  13. package/dist/{chunk-G7NUK3BF.js → chunk-FQF6VHO3.js} +29 -19
  14. package/dist/chunk-FQF6VHO3.js.map +1 -0
  15. package/dist/chunk-H5E6IO2L.js +116 -0
  16. package/dist/chunk-H5E6IO2L.js.map +1 -0
  17. package/dist/{chunk-3R3LHA4Q.js → chunk-I3WF6L43.js} +2 -2
  18. package/dist/{chunk-LJQXQTFC.js → chunk-IAQFZFWD.js} +4 -4
  19. package/dist/{chunk-BRZA7ZCX.js → chunk-IXVGBUWI.js} +5 -5
  20. package/dist/{chunk-2RTBSLSR.js → chunk-ORO2T4K2.js} +19 -5
  21. package/dist/chunk-ORO2T4K2.js.map +1 -0
  22. package/dist/{chunk-A3ZAXL5T.js → chunk-QCX66KBM.js} +3 -3
  23. package/dist/{chunk-VSPC74SS.js → chunk-R7GKQBZJ.js} +10 -9
  24. package/dist/chunk-R7GKQBZJ.js.map +1 -0
  25. package/dist/{chunk-VR6QTK5Z.js → chunk-REHVGFJE.js} +5 -5
  26. package/dist/{chunk-SPQSNZMM.js → chunk-TVEDNGVP.js} +2 -2
  27. package/dist/{chunk-MHAQWMNJ.js → chunk-WUSEZFER.js} +1 -5
  28. package/dist/{chunk-MHAQWMNJ.js.map → chunk-WUSEZFER.js.map} +1 -1
  29. package/dist/commands/build/marketplace.js +4 -4
  30. package/dist/commands/build/plugins.js +6 -6
  31. package/dist/commands/compile.js +12 -12
  32. package/dist/commands/doctor.js +7 -7
  33. package/dist/commands/edit.js +56 -59
  34. package/dist/commands/edit.js.map +1 -1
  35. package/dist/commands/eject.js +10 -10
  36. package/dist/commands/init.js +17 -18
  37. package/dist/commands/list.js +41 -16
  38. package/dist/commands/list.js.map +1 -1
  39. package/dist/commands/new/marketplace.js +4 -4
  40. package/dist/commands/search.js +9 -9
  41. package/dist/commands/share.js +9 -9
  42. package/dist/commands/uninstall.js +25 -24
  43. package/dist/commands/uninstall.js.map +1 -1
  44. package/dist/commands/update.js +6 -6
  45. package/dist/components/common/select-list.js +2 -2
  46. package/dist/components/common/skill-agent-summary.js +3 -3
  47. package/dist/components/common/summary-panel.js +4 -7
  48. package/dist/hooks/init.js +40 -25
  49. package/dist/hooks/init.js.map +1 -1
  50. package/dist/load-agent-defs-5U5KAURA.js +14 -0
  51. package/dist/{recompile-project-agents-6G6M2RS6.js → recompile-project-agents-KYK44C24.js} +8 -8
  52. package/dist/{source-loader-W7XCNKNA.js → source-loader-G5I4RNUP.js} +4 -4
  53. package/package.json +1 -1
  54. package/dist/chunk-2RTBSLSR.js.map +0 -1
  55. package/dist/chunk-AARQBW5L.js.map +0 -1
  56. package/dist/chunk-G7NUK3BF.js.map +0 -1
  57. package/dist/chunk-N33AKFLR.js +0 -24
  58. package/dist/chunk-N33AKFLR.js.map +0 -1
  59. package/dist/chunk-Q6WRR4BN.js +0 -195
  60. package/dist/chunk-Q6WRR4BN.js.map +0 -1
  61. package/dist/chunk-VSPC74SS.js.map +0 -1
  62. package/dist/chunk-WVFBBZEP.js.map +0 -1
  63. package/dist/components/common/scroll-affordance.js +0 -9
  64. package/dist/load-agent-defs-E67DSYTN.js +0 -14
  65. package/dist/source-loader-W7XCNKNA.js.map +0 -1
  66. /package/dist/{chunk-Q4UNHVPX.js.map → chunk-3PJZ4QNJ.js.map} +0 -0
  67. /package/dist/{chunk-3N4FSTVX.js.map → chunk-6PGXTLA4.js.map} +0 -0
  68. /package/dist/{chunk-ITQF35UQ.js.map → chunk-7BHDKEGK.js.map} +0 -0
  69. /package/dist/{chunk-F437ICEG.js.map → chunk-ECPFYHDX.js.map} +0 -0
  70. /package/dist/{chunk-EHJIQDXR.js.map → chunk-EFXVYQGT.js.map} +0 -0
  71. /package/dist/{chunk-3R3LHA4Q.js.map → chunk-I3WF6L43.js.map} +0 -0
  72. /package/dist/{chunk-LJQXQTFC.js.map → chunk-IAQFZFWD.js.map} +0 -0
  73. /package/dist/{chunk-BRZA7ZCX.js.map → chunk-IXVGBUWI.js.map} +0 -0
  74. /package/dist/{chunk-A3ZAXL5T.js.map → chunk-QCX66KBM.js.map} +0 -0
  75. /package/dist/{chunk-VR6QTK5Z.js.map → chunk-REHVGFJE.js.map} +0 -0
  76. /package/dist/{chunk-SPQSNZMM.js.map → chunk-TVEDNGVP.js.map} +0 -0
  77. /package/dist/{components/common/scroll-affordance.js.map → load-agent-defs-5U5KAURA.js.map} +0 -0
  78. /package/dist/{recompile-project-agents-6G6M2RS6.js.map → recompile-project-agents-KYK44C24.js.map} +0 -0
  79. /package/dist/{load-agent-defs-E67DSYTN.js.map → source-loader-G5I4RNUP.js.map} +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  hostAt,
7
7
  loadInstalledConfig,
8
8
  refuseUnofferedPlacements
9
- } from "./chunk-WVFBBZEP.js";
9
+ } from "./chunk-E45IT3HC.js";
10
10
 
11
11
  // src/cli/lib/hosts/configured-placements.ts
12
12
  async function unofferablePlacementsFound(cwd) {
@@ -36,4 +36,4 @@ async function configuredSkillsAt(root) {
36
36
  export {
37
37
  unofferablePlacementsFound
38
38
  };
39
- //# sourceMappingURL=chunk-F437ICEG.js.map
39
+ //# sourceMappingURL=chunk-ECPFYHDX.js.map
@@ -29,12 +29,12 @@ import {
29
29
  sourceFolderName,
30
30
  verbose,
31
31
  writeFile
32
- } from "./chunk-WVFBBZEP.js";
32
+ } from "./chunk-E45IT3HC.js";
33
33
  import {
34
34
  typedEntries,
35
35
  typedFromEntries,
36
36
  typedKeys
37
- } from "./chunk-7OG635DK.js";
37
+ } from "./chunk-AIBVAYHS.js";
38
38
  import {
39
39
  CLAUDE_DIR,
40
40
  DIRS,
@@ -42,7 +42,7 @@ import {
42
42
  STANDARD_DIRS,
43
43
  STANDARD_FILES,
44
44
  effectivelyExcludedSkillIds
45
- } from "./chunk-MHAQWMNJ.js";
45
+ } from "./chunk-WUSEZFER.js";
46
46
 
47
47
  // src/cli/lib/agents/list-compiled-agents.ts
48
48
  import path from "path";
@@ -374,4 +374,4 @@ export {
374
374
  withoutExcludedAssignments,
375
375
  recompileAgents
376
376
  };
377
- //# sourceMappingURL=chunk-EHJIQDXR.js.map
377
+ //# sourceMappingURL=chunk-EFXVYQGT.js.map
@@ -1,23 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- getSkillDisplayName,
4
- inertLine,
3
+ getSkillEntryDisplayName,
5
4
  typedValues
6
- } from "./chunk-7OG635DK.js";
5
+ } from "./chunk-AIBVAYHS.js";
7
6
  import {
8
7
  CLI_COLORS,
9
8
  EJECT_SOURCE,
10
9
  UI_SYMBOLS,
11
10
  isActiveAt,
12
11
  isGlobalTombstone
13
- } from "./chunk-MHAQWMNJ.js";
12
+ } from "./chunk-WUSEZFER.js";
14
13
 
15
14
  // src/cli/components/common/skill-agent-summary.tsx
16
15
  import { Box, Text } from "ink";
17
16
  import "react";
18
17
 
19
18
  // src/cli/lib/configuration/scope-diff.ts
20
- import { difference, partition, unique } from "remeda";
19
+ import { difference, indexBy, partition, unique } from "remeda";
21
20
  var NOTHING = /* @__PURE__ */ new Set();
22
21
  function computeScopeDiff(input) {
23
22
  const { currentSkills, currentAgents, installedSkillConfigs, installedAgentConfigs, isInitMode } = input;
@@ -87,9 +86,13 @@ function skillRowClassifier(installed, overwritten) {
87
86
  return (skill) => ({
88
87
  id: skill.id,
89
88
  source: skill.origin,
90
- status: skillStatus(skill, installedSlots, installedOriginBySlot, overwritten)
89
+ status: skillStatus(skill, installedSlots, installedOriginBySlot, overwritten),
90
+ ...recordedNameOf(skill)
91
91
  });
92
92
  }
93
+ function recordedNameOf(skill) {
94
+ return skill.displayName === void 0 ? {} : { displayName: skill.displayName };
95
+ }
93
96
  function agentRowClassifier(installed, changed) {
94
97
  const installedSlots = installed ? new Set(installed.map((agent) => slotKey(agent.name, agent.scope))) : null;
95
98
  return (agent) => ({ name: agent.name, status: agentStatus(agent, installedSlots, changed) });
@@ -108,7 +111,7 @@ function agentStatus(agent, installedSlots, changed) {
108
111
  return !agent.excluded && changed.has(agent.name) ? "changed" : "unchanged";
109
112
  }
110
113
  function toRemovedSkillRow(skill) {
111
- return { id: skill.id, source: skill.origin, status: "removed" };
114
+ return { id: skill.id, source: skill.origin, status: "removed", ...recordedNameOf(skill) };
112
115
  }
113
116
  function toRemovedAgentRow(agent) {
114
117
  return { name: agent.name, status: "removed" };
@@ -122,9 +125,21 @@ function agentChangesAmong(names, before, after) {
122
125
  return names.flatMap((name) => {
123
126
  const was = agentStateIn(before, name);
124
127
  const is = agentStateIn(after, name);
125
- return was === void 0 || is === void 0 ? [] : [agentChange(was, is)];
128
+ if (was === void 0 || is === void 0) return [];
129
+ return [namedByEntries(agentChange(was, is), before.skills, after.skills)];
126
130
  });
127
131
  }
132
+ function namedByEntries(change, before, after) {
133
+ const namedBy = {
134
+ ...activeEntriesOf(change.loses, before),
135
+ ...activeEntriesOf(change.gains, after)
136
+ };
137
+ return { ...change, namedBy };
138
+ }
139
+ function activeEntriesOf(skillIds, skills) {
140
+ const active = skills.filter((entry) => !entry.excluded && skillIds.includes(entry.id));
141
+ return indexBy(active, ({ id }) => id);
142
+ }
128
143
  function agentStateIn(config, name) {
129
144
  const agent = config.agents.find((entry) => entry.name === name && !entry.excluded);
130
145
  return agent === void 0 ? void 0 : { agent, rows: config.stack?.[name] };
@@ -151,11 +166,6 @@ function assignedSkillIds(rows) {
151
166
 
152
167
  // src/cli/components/common/skill-agent-summary.tsx
153
168
  import { jsx, jsxs } from "react/jsx-runtime";
154
- var NO_NAMES = /* @__PURE__ */ new Map();
155
- function skillNameOf(id, names) {
156
- const recorded = names.get(id);
157
- return recorded === void 0 ? getSkillDisplayName(id) : inertLine(recorded);
158
- }
159
169
  var TableHeader = ({ children }) => /* @__PURE__ */ jsx(Text, { bold: true, color: CLI_COLORS.WARNING, children });
160
170
  var ScopeLabel = ({ children }) => /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WHITE, backgroundColor: CLI_COLORS.LABEL_BG, children: ` ${children} ` });
161
171
  var EjectIcon = () => /* @__PURE__ */ jsxs(Text, { color: CLI_COLORS.WARNING, children: [
@@ -179,10 +189,10 @@ var DIFF_COLOR = {
179
189
  unchanged: CLI_COLORS.NEUTRAL
180
190
  };
181
191
  var NAME_GUTTER_COLUMNS = 3;
182
- var SkillRow = ({ row, name }) => /* @__PURE__ */ jsxs(Box, { width: "50%", paddingRight: NAME_GUTTER_COLUMNS, children: [
192
+ var SkillRow = ({ row }) => /* @__PURE__ */ jsxs(Box, { width: "50%", paddingRight: NAME_GUTTER_COLUMNS, children: [
183
193
  /* @__PURE__ */ jsx(Box, { flexShrink: 0, children: /* @__PURE__ */ jsx(Text, { color: DIFF_COLOR[row.status], children: DIFF_PREFIX[row.status] }) }),
184
194
  /* @__PURE__ */ jsxs(Text, { color: DIFF_COLOR[row.status], children: [
185
- name,
195
+ getSkillEntryDisplayName(row),
186
196
  row.source === EJECT_SOURCE && /* @__PURE__ */ jsx(EjectIcon, {})
187
197
  ] })
188
198
  ] });
@@ -195,7 +205,6 @@ var agentRowKey = (row) => row.status === "removed" ? `removed-${row.name}` : ro
195
205
  var SkillAgentSummary = ({
196
206
  skillConfigs,
197
207
  agentConfigs,
198
- skillNames = NO_NAMES,
199
208
  ...baseline
200
209
  }) => {
201
210
  const diff = computeScopeDiff({
@@ -222,11 +231,11 @@ var SkillAgentSummary = ({
222
231
  /* @__PURE__ */ jsx(TableHeader, { children: "Skills" }),
223
232
  diff.projectSkillRows.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
224
233
  /* @__PURE__ */ jsx(ScopeLabel, { children: "Project" }),
225
- /* @__PURE__ */ jsx(Box, { flexWrap: "wrap", children: diff.projectSkillRows.map((row) => /* @__PURE__ */ jsx(SkillRow, { row, name: skillNameOf(row.id, skillNames) }, skillRowKey(row))) })
234
+ /* @__PURE__ */ jsx(Box, { flexWrap: "wrap", children: diff.projectSkillRows.map((row) => /* @__PURE__ */ jsx(SkillRow, { row }, skillRowKey(row))) })
226
235
  ] }),
227
236
  diff.globalSkillRows.length > 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
228
237
  /* @__PURE__ */ jsx(ScopeLabel, { children: "Global" }),
229
- /* @__PURE__ */ jsx(Box, { flexWrap: "wrap", children: diff.globalSkillRows.map((row) => /* @__PURE__ */ jsx(SkillRow, { row, name: skillNameOf(row.id, skillNames) }, skillRowKey(row))) })
238
+ /* @__PURE__ */ jsx(Box, { flexWrap: "wrap", children: diff.globalSkillRows.map((row) => /* @__PURE__ */ jsx(SkillRow, { row }, skillRowKey(row))) })
230
239
  ] })
231
240
  ]
232
241
  }
@@ -246,8 +255,9 @@ var SkillAgentSummary = ({
246
255
  };
247
256
 
248
257
  export {
258
+ computeScopeDiff,
249
259
  formatScopeTag,
250
260
  agentChangesAmong,
251
261
  SkillAgentSummary
252
262
  };
253
- //# sourceMappingURL=chunk-G7NUK3BF.js.map
263
+ //# sourceMappingURL=chunk-FQF6VHO3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/common/skill-agent-summary.tsx","../src/cli/lib/configuration/scope-diff.ts"],"sourcesContent":["import { Box, Text } from \"ink\";\nimport React from \"react\";\nimport { CLI_COLORS, EJECT_SOURCE, UI_SYMBOLS } from \"../../consts.js\";\nimport { computeScopeDiff } from \"../../lib/configuration/scope-diff.js\";\nimport type {\n AgentDiffRow,\n DiffRowStatus,\n ScopeDiffInput,\n SkillDiffRow,\n} from \"../../lib/configuration/scope-diff.js\";\nimport { getSkillEntryDisplayName } from \"../../lib/matrix/matrix-provider.js\";\nimport type { AgentScopeConfig, SkillConfig } from \"../../types/config.js\";\n\nexport type SkillAgentSummaryProps = Pick<\n ScopeDiffInput,\n | \"installedSkillConfigs\"\n | \"installedAgentConfigs\"\n | \"isInitMode\"\n | \"overwrittenSkillIds\"\n | \"changedAgentNames\"\n> & {\n skillConfigs: SkillConfig[];\n agentConfigs: AgentScopeConfig[];\n};\n\nconst TableHeader: React.FC<{ children: React.ReactNode }> = ({ children }) => (\n <Text bold color={CLI_COLORS.WARNING}>\n {children}\n </Text>\n);\n\nconst ScopeLabel: React.FC<{ children: string }> = ({ children }) => (\n <Text color={CLI_COLORS.WHITE} backgroundColor={CLI_COLORS.LABEL_BG}>\n {` ${children} `}\n </Text>\n);\n\nconst EjectIcon: React.FC = () => <Text color={CLI_COLORS.WARNING}> {UI_SYMBOLS.EJECT}</Text>;\n\nconst DIFF_PREFIX: Record<DiffRowStatus, string> = {\n added: `${UI_SYMBOLS.ADDED} `,\n \"mode-changed\": `${UI_SYMBOLS.CHANGED} `,\n overwritten: `${UI_SYMBOLS.OVERWRITTEN} `,\n changed: `${UI_SYMBOLS.CHANGED} `,\n removed: `${UI_SYMBOLS.REMOVED} `,\n unchanged: `${UI_SYMBOLS.BULLET} `,\n};\n\nconst DIFF_COLOR: Record<DiffRowStatus, string> = {\n added: CLI_COLORS.SUCCESS,\n \"mode-changed\": CLI_COLORS.WARNING,\n overwritten: CLI_COLORS.WARNING,\n changed: CLI_COLORS.WARNING,\n removed: CLI_COLORS.ERROR,\n unchanged: CLI_COLORS.NEUTRAL,\n};\n\n/**\n * Yoga widens a text to whole columns on both sides and Ink draws it from its rounded left, so a\n * name in a half that starts or ends mid-column draws up to two columns past the half: over the\n * next name, or over the table's border. The third column stays blank.\n */\nconst NAME_GUTTER_COLUMNS = 3;\n\n/**\n * A long name wraps under itself, beside a prefix that never shrinks, and carries its mark in its\n * own text: drawn beside the name, the mark covered its last letters.\n */\nconst SkillRow: React.FC<{ row: SkillDiffRow }> = ({ row }) => (\n <Box width=\"50%\" paddingRight={NAME_GUTTER_COLUMNS}>\n <Box flexShrink={0}>\n <Text color={DIFF_COLOR[row.status]}>{DIFF_PREFIX[row.status]}</Text>\n </Box>\n <Text color={DIFF_COLOR[row.status]}>\n {getSkillEntryDisplayName(row)}\n {row.source === EJECT_SOURCE && <EjectIcon />}\n </Text>\n </Box>\n);\n\nconst AgentRow: React.FC<{ row: AgentDiffRow }> = ({ row }) => (\n <Text color={DIFF_COLOR[row.status]}>\n {DIFF_PREFIX[row.status]}\n {row.name}\n </Text>\n);\n\nconst skillRowKey = (row: SkillDiffRow): string =>\n row.status === \"removed\" ? `removed-${row.id}` : row.id;\n\nconst agentRowKey = (row: AgentDiffRow): string =>\n row.status === \"removed\" ? `removed-${row.name}` : row.name;\n\nexport const SkillAgentSummary: React.FC<SkillAgentSummaryProps> = ({\n skillConfigs,\n agentConfigs,\n ...baseline\n}) => {\n const diff = computeScopeDiff({\n currentSkills: skillConfigs,\n currentAgents: agentConfigs,\n ...baseline,\n });\n\n if (!diff.hasContent) return null;\n\n return (\n <Box flexDirection=\"row\" width=\"100%\">\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n flexGrow={2}\n flexBasis={0}\n borderRight={true}\n borderTop={false}\n borderBottom={false}\n borderLeft={false}\n borderColor={CLI_COLORS.NEUTRAL}\n borderRightDimColor\n >\n <TableHeader>Skills</TableHeader>\n {diff.projectSkillRows.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <ScopeLabel>Project</ScopeLabel>\n <Box flexWrap=\"wrap\">\n {diff.projectSkillRows.map((row) => (\n <SkillRow key={skillRowKey(row)} row={row} />\n ))}\n </Box>\n </Box>\n )}\n {diff.globalSkillRows.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <ScopeLabel>Global</ScopeLabel>\n <Box flexWrap=\"wrap\">\n {diff.globalSkillRows.map((row) => (\n <SkillRow key={skillRowKey(row)} row={row} />\n ))}\n </Box>\n </Box>\n )}\n </Box>\n <Box flexDirection=\"column\" flexGrow={1} flexBasis={0} marginLeft={1} paddingLeft={1}>\n <TableHeader>Agents</TableHeader>\n {diff.projectAgentRows.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <ScopeLabel>Project</ScopeLabel>\n <Box flexDirection=\"column\">\n {diff.projectAgentRows.map((row) => (\n <AgentRow key={agentRowKey(row)} row={row} />\n ))}\n </Box>\n </Box>\n )}\n {diff.globalAgentRows.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <ScopeLabel>Global</ScopeLabel>\n <Box flexDirection=\"column\">\n {diff.globalAgentRows.map((row) => (\n <AgentRow key={agentRowKey(row)} row={row} />\n ))}\n </Box>\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import { difference, indexBy, partition, unique } from \"remeda\";\nimport type { AgentScopeConfig, SkillConfig, SkillScope } from \"../../types/config\";\nimport type { AgentName, SkillId, StackAgentConfig } from \"../../types/index\";\nimport { typedValues } from \"../../utils/typed-object\";\nimport { isActiveAt, isGlobalTombstone, type ScopedEntry } from \"./scope-predicates\";\n\nexport type ScopeDiffInput = {\n currentSkills: SkillConfig[];\n currentAgents: AgentScopeConfig[];\n installedSkillConfigs: SkillConfig[] | null;\n installedAgentConfigs: AgentScopeConfig[] | null;\n isInitMode: boolean;\n /** Skills whose files the run writes over where they stand. */\n overwrittenSkillIds?: ReadonlySet<SkillId>;\n /** Sub-agents that keep their slot and still change. */\n changedAgentNames?: ReadonlySet<AgentName>;\n};\n\nexport type DiffRowStatus =\n \"added\" | \"mode-changed\" | \"overwritten\" | \"changed\" | \"removed\" | \"unchanged\";\n\nexport type SkillDiffRow = {\n id: SkillId;\n source: string;\n status: Exclude<DiffRowStatus, \"changed\">;\n /** The name the entry the row was drawn from records; absent where it records none. */\n displayName?: string;\n};\n\nexport type AgentDiffRow = {\n name: AgentName;\n status: Exclude<DiffRowStatus, \"mode-changed\" | \"overwritten\">;\n};\n\nexport type ScopeDiff = {\n projectSkillRows: SkillDiffRow[];\n globalSkillRows: SkillDiffRow[];\n projectAgentRows: AgentDiffRow[];\n globalAgentRows: AgentDiffRow[];\n hasContent: boolean;\n};\n\nconst NOTHING: ReadonlySet<never> = new Set();\n\n/** One scope's share of a roster's diff: the entries listed with a status, then the removals. */\ntype ScopeEntries<Entry> = { listed: Entry[]; removed: Entry[] };\n\ntype RosterDiff<Entry> = Record<SkillScope, ScopeEntries<Entry>>;\n\n/**\n * A tombstone occupies its (id, scope) slot without filling it: it silences a global install at\n * project scope. Slot checks count tombstones; removal and `~` read the active baseline only.\n */\nexport function computeScopeDiff(input: ScopeDiffInput): ScopeDiff {\n const { currentSkills, currentAgents, installedSkillConfigs, installedAgentConfigs, isInitMode } =\n input;\n const overwritten = input.overwrittenSkillIds ?? NOTHING;\n const changed = input.changedAgentNames ?? NOTHING;\n\n const skills = diffRoster(currentSkills, installedSkillConfigs, (skill) => skill.id, isInitMode);\n const agents = diffRoster(\n currentAgents,\n installedAgentConfigs,\n (agent) => agent.name,\n isInitMode,\n );\n const skillRow = skillRowClassifier(installedSkillConfigs, overwritten);\n const agentRow = agentRowClassifier(installedAgentConfigs, changed);\n\n const projectSkillRows = rowsOf(skills.project, skillRow, toRemovedSkillRow);\n const globalSkillRows = rowsOf(skills.global, skillRow, toRemovedSkillRow);\n const projectAgentRows = rowsOf(agents.project, agentRow, toRemovedAgentRow);\n const globalAgentRows = rowsOf(agents.global, agentRow, toRemovedAgentRow);\n\n const hasContent = [projectSkillRows, globalSkillRows, projectAgentRows, globalAgentRows].some(\n (rows) => rows.length > 0,\n );\n\n return { projectSkillRows, globalSkillRows, projectAgentRows, globalAgentRows, hasContent };\n}\n\nfunction diffRoster<Entry extends ScopedEntry>(\n current: Entry[],\n installed: Entry[] | null,\n identityOf: (entry: Entry) => string,\n isInitMode: boolean,\n): RosterDiff<Entry> {\n // The installs the baseline actually records; tombstones are not installs.\n const activeBaseline = (installed ?? []).filter((entry) => !entry.excluded);\n const vacated = vacatedInstalls(activeBaseline, current, identityOf);\n const projectEntries = current.filter((entry) => isActiveAt(entry, \"project\"));\n const claimedByProject = new Set(projectEntries.map(identityOf));\n // A vacated global the project claims is inherited: listed once under Global, never removed.\n const [inheritedGlobals, removedGlobals] = partition(\n vacated.filter((entry) => entry.scope === \"global\"),\n (entry) => claimedByProject.has(identityOf(entry)),\n );\n\n return {\n project: {\n listed: projectEntries,\n removed: vacated.filter((entry) => entry.scope === \"project\"),\n },\n global: {\n listed: [\n ...current.filter((entry) => isActiveAt(entry, \"global\")),\n ...inheritedGlobals,\n ...current.filter(isGlobalTombstone),\n ],\n removed: isInitMode ? [] : removedGlobals,\n },\n };\n}\n\n/** Baseline installs whose slot nothing in current, active or tombstone, occupies. */\nfunction vacatedInstalls<Entry extends ScopedEntry>(\n activeBaseline: Entry[],\n current: Entry[],\n identityOf: (entry: Entry) => string,\n): Entry[] {\n const slotOf = (entry: Entry) => slotKey(identityOf(entry), entry.scope);\n const occupiedSlots = new Set(current.map(slotOf));\n return activeBaseline.filter((install) => !occupiedSlots.has(slotOf(install)));\n}\n\nfunction rowsOf<Entry, Row>(\n entries: ScopeEntries<Entry>,\n toRow: (entry: Entry) => Row,\n toRemovedRow: (entry: Entry) => Row,\n): Row[] {\n return [...entries.listed.map(toRow), ...entries.removed.map(toRemovedRow)];\n}\n\n/** The `(id, scope)` SLOT key this module diffs on, rather than the id alone. */\nfunction slotKey(identity: string, scope: SkillScope | undefined): string {\n return `${identity}:${scope}`;\n}\n\nexport function formatScopeTag(scope: SkillScope): \"[G]\" | \"[P]\" {\n return scope === \"global\" ? \"[G]\" : \"[P]\";\n}\n\nfunction skillRowClassifier(\n installed: SkillConfig[] | null,\n overwritten: ReadonlySet<SkillId>,\n): (skill: SkillConfig) => SkillDiffRow {\n const installedSlots = installed\n ? new Set(installed.map((skill) => slotKey(skill.id, skill.scope)))\n : null;\n const installedOriginBySlot = installed\n ? new Map(\n installed\n .filter((skill) => !skill.excluded)\n .map((skill) => [slotKey(skill.id, skill.scope), skill.origin]),\n )\n : null;\n return (skill) => ({\n id: skill.id,\n source: skill.origin,\n status: skillStatus(skill, installedSlots, installedOriginBySlot, overwritten),\n ...recordedNameOf(skill),\n });\n}\n\nfunction recordedNameOf(skill: SkillConfig): Pick<SkillDiffRow, \"displayName\"> {\n return skill.displayName === undefined ? {} : { displayName: skill.displayName };\n}\n\nfunction agentRowClassifier(\n installed: AgentScopeConfig[] | null,\n changed: ReadonlySet<AgentName>,\n): (agent: AgentScopeConfig) => AgentDiffRow {\n const installedSlots = installed\n ? new Set(installed.map((agent) => slotKey(agent.name, agent.scope)))\n : null;\n return (agent) => ({ name: agent.name, status: agentStatus(agent, installedSlots, changed) });\n}\n\n/**\n * Compares `origin`, which is where a skill's install mode is recorded. An overwrite outranks a\n * mode change: a copy its plugin replaces is deleted, not merely switched. A mask is never written.\n */\nfunction skillStatus(\n skill: SkillConfig,\n installedSlots: Set<string> | null,\n installedOriginBySlot: Map<string, string> | null,\n overwritten: ReadonlySet<SkillId>,\n): SkillDiffRow[\"status\"] {\n const slot = slotKey(skill.id, skill.scope);\n if (installedSlots === null || !installedSlots.has(slot)) return \"added\";\n if (!skill.excluded && overwritten.has(skill.id)) return \"overwritten\";\n\n const installedOrigin = installedOriginBySlot?.get(slot);\n const modeChanged = installedOrigin != null && installedOrigin !== skill.origin;\n return modeChanged ? \"mode-changed\" : \"unchanged\";\n}\n\n/** A mask is never the sub-agent that changes: its active half is. */\nfunction agentStatus(\n agent: AgentScopeConfig,\n installedSlots: Set<string> | null,\n changed: ReadonlySet<AgentName>,\n): AgentDiffRow[\"status\"] {\n const isNew = installedSlots === null || !installedSlots.has(slotKey(agent.name, agent.scope));\n if (isNew) return \"added\";\n return !agent.excluded && changed.has(agent.name) ? \"changed\" : \"unchanged\";\n}\n\nfunction toRemovedSkillRow(skill: SkillConfig): SkillDiffRow {\n return { id: skill.id, source: skill.origin, status: \"removed\", ...recordedNameOf(skill) };\n}\n\nfunction toRemovedAgentRow(agent: AgentScopeConfig): AgentDiffRow {\n return { name: agent.name, status: \"removed\" };\n}\n\n/** A sub-agent that keeps its slot and still changes: the skills its rows gain and lose, and its retunes. */\nexport type AgentChange = {\n name: AgentName;\n scope: SkillScope;\n gains: SkillId[];\n loses: SkillId[];\n settings: SettingChange[];\n /** The entry each is named by: the run's for a skill it gains, the install's for one it loses. */\n namedBy?: Partial<Record<SkillId, Pick<SkillConfig, \"id\" | \"displayName\">>>;\n};\n\n/** `undefined` where the setting is left to its default. */\nexport type SettingChange = {\n setting: AgentSetting;\n from: string | undefined;\n to: string | undefined;\n};\n\ntype AgentSetting = \"model\" | \"codex model\" | \"effort\";\n\nconst AGENT_SETTINGS: ReadonlyArray<\n [AgentSetting, (agent: AgentScopeConfig) => string | undefined]\n> = [\n [\"model\", (agent) => agent.model],\n [\"codex model\", (agent) => agent.codexModel],\n [\"effort\", (agent) => agent.effort],\n];\n\n/** One sub-agent as a config records it: its entry and its skill rows. */\nexport type AgentState = { agent: AgentScopeConfig; rows: StackAgentConfig | undefined };\n\ntype AgentsAndRows = {\n agents: AgentScopeConfig[];\n skills: SkillConfig[];\n stack?: Partial<Record<string, StackAgentConfig>>;\n};\n\n/** How each named sub-agent moves between two configs; one either config lacks is not named. */\nexport function agentChangesAmong(\n names: readonly AgentName[],\n before: AgentsAndRows,\n after: AgentsAndRows,\n): AgentChange[] {\n return names.flatMap((name) => {\n const was = agentStateIn(before, name);\n const is = agentStateIn(after, name);\n if (was === undefined || is === undefined) return [];\n return [namedByEntries(agentChange(was, is), before.skills, after.skills)];\n });\n}\n\nfunction namedByEntries(\n change: AgentChange,\n before: SkillConfig[],\n after: SkillConfig[],\n): AgentChange {\n const namedBy = {\n ...activeEntriesOf(change.loses, before),\n ...activeEntriesOf(change.gains, after),\n };\n return { ...change, namedBy };\n}\n\nfunction activeEntriesOf(skillIds: readonly SkillId[], skills: SkillConfig[]) {\n const active = skills.filter((entry) => !entry.excluded && skillIds.includes(entry.id));\n return indexBy(active, ({ id }) => id);\n}\n\n/** Its active entry, never the mask a project's own copy leaves; `undefined` where none is. */\nfunction agentStateIn(config: AgentsAndRows, name: AgentName): AgentState | undefined {\n const agent = config.agents.find((entry) => entry.name === name && !entry.excluded);\n return agent === undefined ? undefined : { agent, rows: config.stack?.[name] };\n}\n\nexport function agentChange(before: AgentState, after: AgentState): AgentChange {\n const beforeIds = assignedSkillIds(before.rows);\n const afterIds = assignedSkillIds(after.rows);\n\n return {\n name: after.agent.name,\n scope: after.agent.scope,\n gains: difference(afterIds, beforeIds),\n loses: difference(beforeIds, afterIds),\n settings: settingChanges(before.agent, after.agent),\n };\n}\n\nfunction settingChanges(before: AgentScopeConfig, after: AgentScopeConfig): SettingChange[] {\n return AGENT_SETTINGS.filter(([, read]) => read(before) !== read(after)).map(\n ([setting, read]) => ({ setting, from: read(before), to: read(after) }),\n );\n}\n\nfunction assignedSkillIds(rows: StackAgentConfig | undefined): SkillId[] {\n return unique(typedValues(rows ?? {}).flatMap((assignments) => assignments.map(({ id }) => id)));\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ SkillAgentSummary
4
+ } from "./chunk-FQF6VHO3.js";
5
+ import {
6
+ ALL_SKILLS_EJECTED_LABEL,
7
+ CLI_COLORS,
8
+ DEFAULT_PUBLIC_SOURCE_NAME,
9
+ EJECT_SOURCE,
10
+ formatSourceDisplayName
11
+ } from "./chunk-WUSEZFER.js";
12
+
13
+ // src/cli/components/common/summary-panel.tsx
14
+ import { Box, Text, renderToString } from "ink";
15
+ import "react";
16
+ import { unique } from "remeda";
17
+
18
+ // src/cli/components/hooks/use-terminal-dimensions.ts
19
+ import { useState, useEffect } from "react";
20
+ import { useStdout } from "ink";
21
+ var DEFAULT_COLUMNS = 80;
22
+ var DEFAULT_ROWS = 24;
23
+ function dimensionsOf(stdout) {
24
+ return {
25
+ columns: stdout.columns || DEFAULT_COLUMNS,
26
+ rows: stdout.rows || DEFAULT_ROWS
27
+ };
28
+ }
29
+ function useTerminalDimensions() {
30
+ const { stdout } = useStdout();
31
+ const [dimensions, setDimensions] = useState(() => dimensionsOf(stdout));
32
+ useEffect(() => {
33
+ const handleResize = () => {
34
+ setDimensions(dimensionsOf(stdout));
35
+ };
36
+ stdout.on("resize", handleResize);
37
+ return () => {
38
+ stdout.off("resize", handleResize);
39
+ };
40
+ }, [stdout]);
41
+ return dimensions;
42
+ }
43
+
44
+ // src/cli/components/common/summary-panel.tsx
45
+ import { jsx, jsxs } from "react/jsx-runtime";
46
+ function skillsTheHeaderNames({
47
+ skillConfigs,
48
+ installedSkillConfigs
49
+ }) {
50
+ return skillConfigs.length > 0 ? skillConfigs : installedSkillConfigs ?? [];
51
+ }
52
+ function formatSkillMarketplaces(skillConfigs) {
53
+ if (skillConfigs.length === 0) return formatSourceDisplayName(DEFAULT_PUBLIC_SOURCE_NAME);
54
+ const marketplaceNames = unique(
55
+ skillConfigs.map((config) => config.origin).filter((origin) => origin !== EJECT_SOURCE)
56
+ );
57
+ if (marketplaceNames.length === 0) return ALL_SKILLS_EJECTED_LABEL;
58
+ return marketplaceNames.map((name) => formatSourceDisplayName(name)).sort().join(" \xB7 ");
59
+ }
60
+ var PanelHeader = ({ sourceNames, stackName }) => /* @__PURE__ */ jsxs(
61
+ Box,
62
+ {
63
+ flexDirection: "column",
64
+ borderStyle: "single",
65
+ borderBottom: true,
66
+ borderTop: false,
67
+ borderLeft: false,
68
+ borderRight: false,
69
+ borderColor: CLI_COLORS.NEUTRAL,
70
+ borderBottomDimColor: true,
71
+ paddingBottom: 1,
72
+ marginBottom: 1,
73
+ children: [
74
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", columnGap: 1, children: [
75
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, bold: true, children: "Marketplace" }),
76
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.NEUTRAL, children: sourceNames })
77
+ ] }),
78
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", columnGap: 1, children: [
79
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.WARNING, bold: true, children: "Stack" }),
80
+ /* @__PURE__ */ jsx(Text, { color: CLI_COLORS.NEUTRAL, children: stackName ?? "none" })
81
+ ] })
82
+ ]
83
+ }
84
+ );
85
+ var SummaryPanel = ({
86
+ stackName,
87
+ headerSkillConfigs,
88
+ ...summary
89
+ }) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: CLI_COLORS.NEUTRAL, paddingX: 2, children: [
90
+ /* @__PURE__ */ jsx(
91
+ PanelHeader,
92
+ {
93
+ sourceNames: formatSkillMarketplaces(headerSkillConfigs ?? skillsTheHeaderNames(summary)),
94
+ stackName
95
+ }
96
+ ),
97
+ /* @__PURE__ */ jsx(SkillAgentSummary, { ...summary })
98
+ ] });
99
+ function summaryPanelText(props, columns = dimensionsOf(process.stdout).columns) {
100
+ return renderToString(/* @__PURE__ */ jsx(SummaryPanel, { ...props }), { columns });
101
+ }
102
+ function summaryPanelBlock(panel, linesUnder, statements) {
103
+ return [
104
+ summaryPanelText(panel),
105
+ ...linesUnder,
106
+ ...statements.flatMap((statement) => ["", statement]),
107
+ ""
108
+ ];
109
+ }
110
+
111
+ export {
112
+ useTerminalDimensions,
113
+ summaryPanelText,
114
+ summaryPanelBlock
115
+ };
116
+ //# sourceMappingURL=chunk-H5E6IO2L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/components/common/summary-panel.tsx","../src/cli/components/hooks/use-terminal-dimensions.ts"],"sourcesContent":["import { Box, Text, renderToString } from \"ink\";\nimport React from \"react\";\nimport { unique } from \"remeda\";\nimport {\n ALL_SKILLS_EJECTED_LABEL,\n CLI_COLORS,\n DEFAULT_PUBLIC_SOURCE_NAME,\n EJECT_SOURCE,\n formatSourceDisplayName,\n} from \"../../consts.js\";\nimport type { SkillConfig } from \"../../types/config.js\";\nimport { dimensionsOf } from \"../hooks/use-terminal-dimensions.js\";\nimport { SkillAgentSummary, type SkillAgentSummaryProps } from \"./skill-agent-summary.js\";\n\nexport type SummaryPanelProps = SkillAgentSummaryProps & {\n /** `undefined` when the configuration was built from no stack. */\n stackName: string | undefined;\n /** Where set, the skills the header names in place of those the panel leaves in place. */\n headerSkillConfigs?: SkillConfig[];\n};\n\n/**\n * The skills the panel leaves in place; leaving none, those it removes. The default marketplace is\n * only for a panel with no skill either way.\n */\nfunction skillsTheHeaderNames({\n skillConfigs,\n installedSkillConfigs,\n}: SkillAgentSummaryProps): SkillConfig[] {\n return skillConfigs.length > 0 ? skillConfigs : (installedSkillConfigs ?? []);\n}\n\n/**\n * No skills shows the default marketplace; all-ejected names none. Tombstoned entries count: the\n * summary below renders them as rows.\n */\nfunction formatSkillMarketplaces(skillConfigs: SkillConfig[]): string {\n if (skillConfigs.length === 0) return formatSourceDisplayName(DEFAULT_PUBLIC_SOURCE_NAME);\n\n const marketplaceNames = unique(\n skillConfigs.map((config) => config.origin).filter((origin) => origin !== EJECT_SOURCE),\n );\n if (marketplaceNames.length === 0) return ALL_SKILLS_EJECTED_LABEL;\n\n return marketplaceNames\n .map((name) => formatSourceDisplayName(name))\n .sort()\n .join(\" · \");\n}\n\ntype PanelHeaderProps = {\n sourceNames: string;\n stackName: string | undefined;\n};\n\nconst PanelHeader: React.FC<PanelHeaderProps> = ({ sourceNames, stackName }) => (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderBottom={true}\n borderTop={false}\n borderLeft={false}\n borderRight={false}\n borderColor={CLI_COLORS.NEUTRAL}\n borderBottomDimColor\n paddingBottom={1}\n marginBottom={1}\n >\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Marketplace\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{sourceNames}</Text>\n </Box>\n <Box flexDirection=\"row\" columnGap={1}>\n <Text color={CLI_COLORS.WARNING} bold>\n Stack\n </Text>\n <Text color={CLI_COLORS.NEUTRAL}>{stackName ?? \"none\"}</Text>\n </Box>\n </Box>\n);\n\nconst SummaryPanel: React.FC<SummaryPanelProps> = ({\n stackName,\n headerSkillConfigs,\n ...summary\n}) => (\n <Box flexDirection=\"column\" borderStyle=\"single\" borderColor={CLI_COLORS.NEUTRAL} paddingX={2}>\n <PanelHeader\n sourceNames={formatSkillMarketplaces(headerSkillConfigs ?? skillsTheHeaderNames(summary))}\n stackName={stackName}\n />\n <SkillAgentSummary {...summary} />\n </Box>\n);\n\n/**\n * The whole panel as text, drawn once: printed, it scrolls with the terminal like any other line,\n * and a run with no terminal prints the same thing.\n */\nexport function summaryPanelText(\n props: SummaryPanelProps,\n columns: number = dimensionsOf(process.stdout).columns,\n): string {\n return renderToString(<SummaryPanel {...props} />, { columns });\n}\n\n/**\n * What a question shows, or where none is asked, what prints in its place: the panel, the lines\n * under it marking what it cannot show, then each statement after a blank line, and a blank line\n * before what follows.\n */\nexport function summaryPanelBlock(\n panel: SummaryPanelProps,\n linesUnder: readonly string[],\n statements: readonly string[],\n): string[] {\n return [\n summaryPanelText(panel),\n ...linesUnder,\n ...statements.flatMap((statement) => [\"\", statement]),\n \"\",\n ];\n}\n","import { useState, useEffect } from \"react\";\nimport { useStdout } from \"ink\";\n\nconst DEFAULT_COLUMNS = 80;\nconst DEFAULT_ROWS = 24;\n\nexport type TerminalDimensions = {\n columns: number;\n rows: number;\n};\n\n/** A stream that is not a terminal reports no size, so it gets the defaults. */\nexport function dimensionsOf(stdout: NodeJS.WriteStream): TerminalDimensions {\n return {\n columns: stdout.columns || DEFAULT_COLUMNS,\n rows: stdout.rows || DEFAULT_ROWS,\n };\n}\n\nexport function useTerminalDimensions(): TerminalDimensions {\n const { stdout } = useStdout();\n\n const [dimensions, setDimensions] = useState<TerminalDimensions>(() => dimensionsOf(stdout));\n\n useEffect(() => {\n const handleResize = () => {\n setDimensions(dimensionsOf(stdout));\n };\n\n stdout.on(\"resize\", handleResize);\n return () => {\n stdout.off(\"resize\", handleResize);\n };\n }, [stdout]);\n\n return dimensions;\n}\n"],"mappings":";;;;;;;;;;;;;AAAA,SAAS,KAAK,MAAM,sBAAsB;AAC1C,OAAkB;AAClB,SAAS,cAAc;;;ACFvB,SAAS,UAAU,iBAAiB;AACpC,SAAS,iBAAiB;AAE1B,IAAM,kBAAkB;AACxB,IAAM,eAAe;AAQd,SAAS,aAAa,QAAgD;AAC3E,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B,MAAM,OAAO,QAAQ;AAAA,EACvB;AACF;AAEO,SAAS,wBAA4C;AAC1D,QAAM,EAAE,OAAO,IAAI,UAAU;AAE7B,QAAM,CAAC,YAAY,aAAa,IAAI,SAA6B,MAAM,aAAa,MAAM,CAAC;AAE3F,YAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACzB,oBAAc,aAAa,MAAM,CAAC;AAAA,IACpC;AAEA,WAAO,GAAG,UAAU,YAAY;AAChC,WAAO,MAAM;AACX,aAAO,IAAI,UAAU,YAAY;AAAA,IACnC;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO;AACT;;;ADgCI,SACE,KADF;AA3CJ,SAAS,qBAAqB;AAAA,EAC5B;AAAA,EACA;AACF,GAA0C;AACxC,SAAO,aAAa,SAAS,IAAI,eAAgB,yBAAyB,CAAC;AAC7E;AAMA,SAAS,wBAAwB,cAAqC;AACpE,MAAI,aAAa,WAAW,EAAG,QAAO,wBAAwB,0BAA0B;AAExF,QAAM,mBAAmB;AAAA,IACvB,aAAa,IAAI,CAAC,WAAW,OAAO,MAAM,EAAE,OAAO,CAAC,WAAW,WAAW,YAAY;AAAA,EACxF;AACA,MAAI,iBAAiB,WAAW,EAAG,QAAO;AAE1C,SAAO,iBACJ,IAAI,CAAC,SAAS,wBAAwB,IAAI,CAAC,EAC3C,KAAK,EACL,KAAK,QAAK;AACf;AAOA,IAAM,cAA0C,CAAC,EAAE,aAAa,UAAU,MACxE;AAAA,EAAC;AAAA;AAAA,IACC,eAAc;AAAA,IACd,aAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,aAAa,WAAW;AAAA,IACxB,sBAAoB;AAAA,IACpB,eAAe;AAAA,IACf,cAAc;AAAA,IAEd;AAAA,2BAAC,OAAI,eAAc,OAAM,WAAW,GAClC;AAAA,4BAAC,QAAK,OAAO,WAAW,SAAS,MAAI,MAAC,yBAEtC;AAAA,QACA,oBAAC,QAAK,OAAO,WAAW,SAAU,uBAAY;AAAA,SAChD;AAAA,MACA,qBAAC,OAAI,eAAc,OAAM,WAAW,GAClC;AAAA,4BAAC,QAAK,OAAO,WAAW,SAAS,MAAI,MAAC,mBAEtC;AAAA,QACA,oBAAC,QAAK,OAAO,WAAW,SAAU,uBAAa,QAAO;AAAA,SACxD;AAAA;AAAA;AACF;AAGF,IAAM,eAA4C,CAAC;AAAA,EACjD;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE,qBAAC,OAAI,eAAc,UAAS,aAAY,UAAS,aAAa,WAAW,SAAS,UAAU,GAC1F;AAAA;AAAA,IAAC;AAAA;AAAA,MACC,aAAa,wBAAwB,sBAAsB,qBAAqB,OAAO,CAAC;AAAA,MACxF;AAAA;AAAA,EACF;AAAA,EACA,oBAAC,qBAAmB,GAAG,SAAS;AAAA,GAClC;AAOK,SAAS,iBACd,OACA,UAAkB,aAAa,QAAQ,MAAM,EAAE,SACvC;AACR,SAAO,eAAe,oBAAC,gBAAc,GAAG,OAAO,GAAI,EAAE,QAAQ,CAAC;AAChE;AAOO,SAAS,kBACd,OACA,YACA,YACU;AACV,SAAO;AAAA,IACL,iBAAiB,KAAK;AAAA,IACtB,GAAG;AAAA,IACH,GAAG,WAAW,QAAQ,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;AAAA,IACpD;AAAA,EACF;AACF;","names":[]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CLI_COLORS,
4
4
  UI_SYMBOLS
5
- } from "./chunk-MHAQWMNJ.js";
5
+ } from "./chunk-WUSEZFER.js";
6
6
 
7
7
  // src/cli/components/common/select-list.tsx
8
8
  import { useCallback as useCallback2 } from "react";
@@ -103,4 +103,4 @@ function SelectList({
103
103
  export {
104
104
  SelectList
105
105
  };
106
- //# sourceMappingURL=chunk-3R3LHA4Q.js.map
106
+ //# sourceMappingURL=chunk-I3WF6L43.js.map
@@ -50,7 +50,7 @@ import {
50
50
  verbose,
51
51
  warn,
52
52
  writeFile
53
- } from "./chunk-WVFBBZEP.js";
53
+ } from "./chunk-E45IT3HC.js";
54
54
  import {
55
55
  BUILT_IN_MATRIX,
56
56
  getCategoryDomain,
@@ -60,7 +60,7 @@ import {
60
60
  typedEntries,
61
61
  typedKeys,
62
62
  typedValues
63
- } from "./chunk-7OG635DK.js";
63
+ } from "./chunk-AIBVAYHS.js";
64
64
  import {
65
65
  CLI_COLORS,
66
66
  CLI_INVOKE_COMMAND,
@@ -75,7 +75,7 @@ import {
75
75
  isActiveAt,
76
76
  orderDomains,
77
77
  seedExternalSkillSchema
78
- } from "./chunk-MHAQWMNJ.js";
78
+ } from "./chunk-WUSEZFER.js";
79
79
 
80
80
  // src/cli/utils/terminal.ts
81
81
  function clearTerminalScreen() {
@@ -1093,4 +1093,4 @@ export {
1093
1093
  installsAtHome,
1094
1094
  BaseCommand
1095
1095
  };
1096
- //# sourceMappingURL=chunk-LJQXQTFC.js.map
1096
+ //# sourceMappingURL=chunk-IAQFZFWD.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  listAgentMdFiles
4
- } from "./chunk-EHJIQDXR.js";
4
+ } from "./chunk-EFXVYQGT.js";
5
5
  import {
6
6
  agentCodec,
7
7
  agentFrontmatterValidationSchema,
@@ -27,17 +27,17 @@ import {
27
27
  warn,
28
28
  writeContentHash,
29
29
  writePluginManifest
30
- } from "./chunk-WVFBBZEP.js";
30
+ } from "./chunk-E45IT3HC.js";
31
31
  import {
32
32
  plural
33
- } from "./chunk-7OG635DK.js";
33
+ } from "./chunk-AIBVAYHS.js";
34
34
  import {
35
35
  DEFAULT_VERSION,
36
36
  DIRS,
37
37
  PLUGIN_MANIFEST_DIR,
38
38
  PLUGIN_MANIFEST_FILE,
39
39
  PROJECT_ROOT
40
- } from "./chunk-MHAQWMNJ.js";
40
+ } from "./chunk-WUSEZFER.js";
41
41
 
42
42
  // src/cli/lib/agents/agent-fetcher.ts
43
43
  import path from "path";
@@ -157,4 +157,4 @@ export {
157
157
  compileAllAgentPlugins,
158
158
  printAgentCompilationSummary
159
159
  };
160
- //# sourceMappingURL=chunk-BRZA7ZCX.js.map
160
+ //# sourceMappingURL=chunk-IXVGBUWI.js.map
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  chooseProviderForThisRun,
4
- detectInstallations
5
- } from "./chunk-WVFBBZEP.js";
4
+ detectInstallations,
5
+ providerInUse
6
+ } from "./chunk-E45IT3HC.js";
6
7
  import {
7
8
  CLI_INVOKE_COMMAND,
8
9
  EDITOR_URL,
9
10
  PROVIDERS
10
- } from "./chunk-MHAQWMNJ.js";
11
+ } from "./chunk-WUSEZFER.js";
11
12
 
12
13
  // src/cli/lib/installation/provider-flag.ts
13
14
  import os from "os";
@@ -23,6 +24,17 @@ function providerNamedBy(flagValue) {
23
24
  if (flagValue === void 0) return void 0;
24
25
  return PROVIDERS.find((provider) => provider === flagValue);
25
26
  }
27
+ var PROVIDER_FLAG = "--provider";
28
+ var PROVIDER_FLAG_WITH_ITS_VALUE = `${PROVIDER_FLAG}=`;
29
+ var END_OF_FLAGS = "--";
30
+ function providerNamedIn(argv) {
31
+ const end = argv.indexOf(END_OF_FLAGS);
32
+ const flags = end === -1 ? argv : argv.slice(0, end);
33
+ const spaced = flags.indexOf(PROVIDER_FLAG);
34
+ if (spaced !== -1) return providerNamedBy(flags[spaced + 1]);
35
+ const joined = flags.find((token) => token.startsWith(PROVIDER_FLAG_WITH_ITS_VALUE));
36
+ return providerNamedBy(joined?.slice(PROVIDER_FLAG_WITH_ITS_VALUE.length));
37
+ }
26
38
  function providerNeedsAConfigurationToInstall() {
27
39
  return `--provider names which installation to create and needs the configuration to create it from, so it is only meaningful beside --from. Build one at ${EDITOR_URL}, then run '${CLI_INVOKE_COMMAND} init --from <id> --provider <provider>'.`;
28
40
  }
@@ -63,8 +75,9 @@ async function ambiguityFinding(cwd) {
63
75
  if (providers.length <= 1) return null;
64
76
  return ambiguousInstallation("every command that acts on one", providers, scopeRoot);
65
77
  }
66
- async function otherInstallationsInThisScope(cwd, showing) {
78
+ async function otherInstallationsInThisScope(cwd) {
67
79
  const { scopeRoot, providers } = await installationsInPlay(cwd);
80
+ const showing = providerInUse(scopeRoot);
68
81
  const others = providers.filter((provider) => provider !== showing);
69
82
  if (others.length === 0) return null;
70
83
  return `${scopeRoot} holds ${providers.length} installations \u2014 ${providers.join(" and ")} \u2014 and this is the ${showing} one. Show another with --provider <${providers.join("|")}>.`;
@@ -73,10 +86,11 @@ async function otherInstallationsInThisScope(cwd, showing) {
73
86
  export {
74
87
  providerFlag,
75
88
  providerNamedBy,
89
+ providerNamedIn,
76
90
  providerNeedsAConfigurationToInstall,
77
91
  refuseAnAmbiguousInstallation,
78
92
  installationToName,
79
93
  ambiguityFinding,
80
94
  otherInstallationsInThisScope
81
95
  };
82
- //# sourceMappingURL=chunk-2RTBSLSR.js.map
96
+ //# sourceMappingURL=chunk-ORO2T4K2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/installation/provider-flag.ts"],"sourcesContent":["/**\n * `--provider`: names the installation where the folder cannot — a greenfield `init --from`, or a\n * scope holding both providers, where acting commands refuse until it is given.\n */\n\nimport os from \"os\";\n\nimport { Flags } from \"@oclif/core\";\n\nimport { PROVIDERS, EDITOR_URL, CLI_INVOKE_COMMAND, type Provider } from \"../../consts.js\";\nimport { detectInstallations, type DetectedInstallation } from \"./detect-installations.js\";\nimport { chooseProviderForThisRun, providerInUse } from \"./install-layout.js\";\n\n/** A factory because oclif mutates flag definitions, so commands must not share one. */\nexport function providerFlag() {\n return Flags.string({\n description: \"Which provider's installation this run is about\",\n helpValue: `<${PROVIDERS.join(\"|\")}>`,\n options: [...PROVIDERS],\n });\n}\n\n/** oclif has already rejected unlisted values; this only narrows. */\nexport function providerNamedBy(flagValue: string | undefined): Provider | undefined {\n if (flagValue === undefined) return undefined;\n return PROVIDERS.find((provider) => provider === flagValue);\n}\n\nconst PROVIDER_FLAG = \"--provider\";\nconst PROVIDER_FLAG_WITH_ITS_VALUE = `${PROVIDER_FLAG}=`;\nconst END_OF_FLAGS = \"--\";\n\n/**\n * For a run oclif has not parsed yet: `--provider <name>` or `--provider=<name>`, ahead of any\n * `--`; a value naming no provider names none.\n */\nexport function providerNamedIn(argv: readonly string[]): Provider | undefined {\n const end = argv.indexOf(END_OF_FLAGS);\n const flags = end === -1 ? argv : argv.slice(0, end);\n\n const spaced = flags.indexOf(PROVIDER_FLAG);\n if (spaced !== -1) return providerNamedBy(flags[spaced + 1]);\n\n const joined = flags.find((token) => token.startsWith(PROVIDER_FLAG_WITH_ITS_VALUE));\n return providerNamedBy(joined?.slice(PROVIDER_FLAG_WITH_ITS_VALUE.length));\n}\n\nexport function providerNeedsAConfigurationToInstall(): string {\n return (\n `--provider names which installation to create and needs the configuration to create it ` +\n `from, so it is only meaningful beside --from. Build one at ${EDITOR_URL}, then run ` +\n `'${CLI_INVOKE_COMMAND} init --from <id> --provider <provider>'.`\n );\n}\n\nfunction ambiguousInstallation(\n subject: string,\n providers: readonly Provider[],\n scopeRoot: string,\n): string {\n return (\n `${scopeRoot} holds ${providers.length} installations — ${providers.join(\" and \")} — so ` +\n `${subject} cannot tell which one you mean. Name it with --provider <${providers.join(\"|\")}>. ` +\n `Nothing has been changed.`\n );\n}\n\ntype InstallationsInPlay = {\n scopeRoot: string;\n providers: Provider[];\n};\n\n/** The project's installations, or the global ones only when the project has none. */\nasync function installationsInPlay(cwd: string): Promise<InstallationsInPlay> {\n const found = await detectInstallations(cwd);\n const inTheProject = atScope(found, \"project\");\n\n if (inTheProject.length > 0) return { scopeRoot: cwd, providers: providersOf(inTheProject) };\n return { scopeRoot: os.homedir(), providers: providersOf(atScope(found, \"global\")) };\n}\n\nfunction atScope(\n found: readonly DetectedInstallation[],\n scope: DetectedInstallation[\"scope\"],\n): DetectedInstallation[] {\n return found.filter((installation) => installation.scope === scope);\n}\n\nfunction providersOf(installations: readonly DetectedInstallation[]): Provider[] {\n return installations.map((installation) => installation.provider);\n}\n\n/**\n * A named provider is committed for the run; two installations and no flag call `onAmbiguous`\n * (the command's `this.error`); otherwise nothing happens.\n */\nexport async function refuseAnAmbiguousInstallation(\n cwd: string,\n subject: string,\n named: Provider | undefined,\n onAmbiguous: (message: string) => never,\n): Promise<void> {\n if (named !== undefined) {\n chooseProviderForThisRun(named);\n return;\n }\n\n const { scopeRoot, providers } = await installationsInPlay(cwd);\n if (providers.length <= 1) return;\n\n onAmbiguous(ambiguousInstallation(subject, providers, scopeRoot));\n}\n\n/** The non-refusing read the remedies hand a command out from, so they and the refusal agree. */\nexport async function providersInPlay(cwd: string): Promise<Provider[]> {\n return (await installationsInPlay(cwd)).providers;\n}\n\n/**\n * Which installation a handed-out acting command must name: the one the run named, else the choice\n * where two are in play, since a bare one refuses there.\n */\nexport async function installationToName(\n cwd: string,\n named: Provider | undefined,\n): Promise<Provider | Provider[] | undefined> {\n if (named !== undefined) return named;\n\n const providers = await providersInPlay(cwd);\n return providers.length > 1 ? providers : undefined;\n}\n\n/** The non-refusing form, for `doctor`. */\nexport async function ambiguityFinding(cwd: string): Promise<string | null> {\n const { scopeRoot, providers } = await installationsInPlay(cwd);\n if (providers.length <= 1) return null;\n\n return ambiguousInstallation(\"every command that acts on one\", providers, scopeRoot);\n}\n\n/**\n * For `list`: names the other installation in the scope, or `null` when there is none. The one\n * shown is read off the scope the roster came from, as `detectInstallation` reads it.\n */\nexport async function otherInstallationsInThisScope(cwd: string): Promise<string | null> {\n const { scopeRoot, providers } = await installationsInPlay(cwd);\n const showing = providerInUse(scopeRoot);\n const others = providers.filter((provider) => provider !== showing);\n if (others.length === 0) return null;\n\n return (\n `${scopeRoot} holds ${providers.length} installations — ${providers.join(\" and \")} — and this ` +\n `is the ${showing} one. Show another with --provider <${providers.join(\"|\")}>.`\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateText
4
- } from "./chunk-7OG635DK.js";
4
+ } from "./chunk-AIBVAYHS.js";
5
5
  import {
6
6
  SEED_API_URL,
7
7
  seedPayloadSchema
8
- } from "./chunk-MHAQWMNJ.js";
8
+ } from "./chunk-WUSEZFER.js";
9
9
 
10
10
  // ../../node_modules/hono/dist/utils/cookie.js
11
11
  var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
@@ -425,4 +425,4 @@ export {
425
425
  jsonBodyOrUndefined,
426
426
  arrivedAsText
427
427
  };
428
- //# sourceMappingURL=chunk-A3ZAXL5T.js.map
428
+ //# sourceMappingURL=chunk-QCX66KBM.js.map
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  compileAgents,
4
4
  withCatalogueSeatedFor
5
- } from "./chunk-VR6QTK5Z.js";
5
+ } from "./chunk-REHVGFJE.js";
6
6
  import {
7
7
  loadAgentDefs
8
- } from "./chunk-ITQF35UQ.js";
8
+ } from "./chunk-7BHDKEGK.js";
9
9
  import {
10
10
  ConfigLoadError,
11
11
  EXTRACTED_FIELDS,
@@ -53,12 +53,12 @@ import {
53
53
  warn,
54
54
  withGateToken,
55
55
  writeFile
56
- } from "./chunk-WVFBBZEP.js";
56
+ } from "./chunk-E45IT3HC.js";
57
57
  import {
58
58
  matrix,
59
59
  typedEntries,
60
60
  typedKeys
61
- } from "./chunk-7OG635DK.js";
61
+ } from "./chunk-AIBVAYHS.js";
62
62
  import {
63
63
  CLI_INVOKE_COMMAND,
64
64
  CODEX_MODEL_NAMES,
@@ -76,7 +76,7 @@ import {
76
76
  isExclusiveCategory,
77
77
  isGlobalTombstone,
78
78
  skillDomain
79
- } from "./chunk-MHAQWMNJ.js";
79
+ } from "./chunk-WUSEZFER.js";
80
80
 
81
81
  // src/cli/lib/operations/source/load-source.ts
82
82
  async function loadSource(options) {
@@ -146,6 +146,7 @@ export type SkillConfig = {
146
146
  id: SkillId
147
147
  scope: 'project' | 'global'
148
148
  origin: string
149
+ displayName?: string
149
150
  excluded?: boolean
150
151
  }
151
152
 
@@ -1231,7 +1232,7 @@ var NOTHING_RECOMPILED = {
1231
1232
  };
1232
1233
  async function recompilePropagated(projectDirs, pairsRewritten) {
1233
1234
  if (projectDirs.length === 0) return NOTHING_RECOMPILED;
1234
- const { recompilePropagatedProjectAgents } = await import("./recompile-project-agents-6G6M2RS6.js");
1235
+ const { recompilePropagatedProjectAgents } = await import("./recompile-project-agents-KYK44C24.js");
1235
1236
  return recompilePropagatedProjectAgents(projectDirs, pairsRewritten);
1236
1237
  }
1237
1238
  function pairRewriteSummary(projectDirs, pairsRewritten) {
@@ -1327,7 +1328,7 @@ async function applyConsequences(globalConfig, changes, deps, provider, currentP
1327
1328
  function lazyGateDeps(projectDir) {
1328
1329
  return {
1329
1330
  loadMatrix: async () => {
1330
- const { loadSkillsMatrixFromSource: loadSkillsMatrixFromSource2 } = await import("./source-loader-W7XCNKNA.js");
1331
+ const { loadSkillsMatrixFromSource: loadSkillsMatrixFromSource2 } = await import("./source-loader-G5I4RNUP.js");
1331
1332
  const { matrix: matrix2 } = await loadSkillsMatrixFromSource2({
1332
1333
  projectDir,
1333
1334
  skipExtraSources: true,
@@ -1336,7 +1337,7 @@ function lazyGateDeps(projectDir) {
1336
1337
  return matrix2;
1337
1338
  },
1338
1339
  loadAgents: async () => {
1339
- const { loadAgentDefs: loadAgentDefs2 } = await import("./load-agent-defs-E67DSYTN.js");
1340
+ const { loadAgentDefs: loadAgentDefs2 } = await import("./load-agent-defs-5U5KAURA.js");
1340
1341
  return (await loadAgentDefs2()).agents;
1341
1342
  }
1342
1343
  };
@@ -1664,4 +1665,4 @@ export {
1664
1665
  compileAgentsAllScopes,
1665
1666
  compileProjectScope
1666
1667
  };
1667
- //# sourceMappingURL=chunk-VSPC74SS.js.map
1668
+ //# sourceMappingURL=chunk-R7GKQBZJ.js.map